Skip to main content
A stream that ends without a final transcript has failed. The last partial transcript of a failed stream is incomplete, even when it looks like a full sentence.

Error categories

Branch on the category, not on the message text, because the message text can change without notice. Each client uses its own name for each category:
The Go and Rust READMEs show how to check the category and read the request ID.
Before a WebSocket stream starts, the server can refuse the upgrade. It sends an HTTP response, and no error event follows.

Decide whether to retry

Retry only when you still have the audio, and always retry on a new stream. The SDK does not retry or send audio again on its own. Keep the transcript of each attempt separate, and log the request ID of each attempt. A resource-limit error does not always say whether the request went over a limit or the service had no capacity for it. Handle a resource-limit error in this order:
  1. Compare what you sent with the limits that you can measure. These are the size of each message and of the utterance, the context terms, and the 120-second limit. If the request went over a limit, fix the request rather than retry it. For example, a direct client that sent an audio message over 64 KiB must split that message, not shorten the utterance.
  2. If the request is within these limits, the cause is unknown. Retry a small number of times, such as two or three. Use backoff and a new stream for each attempt.
  3. If the error continues, the likely cause is the model’s context. This cause comes back on every retry of the same audio. Split the audio across streams, or shorten the context terms.
The time of the error helps you find the cause: A timeout comes back on retry if you do not fix its cause. To prevent one, send start or config as soon as you connect, send audio through pauses, and end each utterance well before the 120-second limit.

Limits

Two of these limits deserve more explanation: 15 seconds without audio. These events change the timer: Model context. The model reads the utterance’s audio, your context terms, and the transcript so far as one input. That input has a fixed maximum size, and the output contract decides whether the input grows with the utterance:
  • Revised hypotheses: the SDK uses this contract. The model reads all of the audio again for each update, so the context grows with the utterance. A long utterance can run out of context before the 120-second limit. The service never returns a shorter transcript in place of the error.
  • Append fragments: the model recognizes each five-second window on its own, so the context does not grow with the utterance.
In Rime’s tests with English speech, revised-hypotheses streams ran out of context after about 90 to 110 seconds of speech. gRPC Transcribe lasted about 10 seconds longer. Fast speech, a long list of context terms, and silence in the stream fill the context sooner. No speaking rate in words per minute guarantees a length, so split long turns and recordings well before this point.

Common problems

The SDK fails as soon as you create the client

If RIME_API_KEY is missing or empty when you create the client, Python and Node.js raise RimeAuthenticationError at that point, before any request. The SDK does not read .env files, so set the variable in the environment that runs your code, and keep its value out of logs.

Rime refuses the API key

If Rime does not accept the key, it refuses the stream before the stream starts. The SDK raises its authentication error, a WebSocket upgrade gets HTTP 401, and gRPC returns UNAUTHENTICATED. Check that the key is current, or create a new key.

Words repeat in the transcript

Your code appends partial transcripts. Replace each one instead.

Partials arrive, but no final transcript

The stream still waits for the end of the audio. End the audio source:

The stream times out during a pause

The service got no audio for 15 seconds. Send captured audio through every pause. If a step before your backend drops silent frames, fill the gap with frames of zeros.

The transcript is poor or empty

Check these items in order:
  1. Language. Speech in a language other than the one that you selected returns a poor transcript, not an error.
  2. Audio format. The SDK reads every byte as PCM16 samples. Remove a WAV header, and decode MP3 or mu-law audio, before you send it. Set input_format to the rate and channel count of your capture.
  3. Silence. An empty final transcript is a successful result for audio with no recognizable speech.
  4. Names and jargon. Add context terms for words that the model gets wrong.

A long turn or recording fails

A resource-limit error late in a long utterance usually means that the utterance ran out of model context. A long call made of short turns does not have this problem, because each turn has its own stream. A retry of the same audio fails again, and gRPC Transcribe holds only a little more audio, so split long audio across streams:
  • Live audio: End the utterance at the first pause after about a minute of speech, and start the next stream immediately. Split long turns at pauses shows how to do this with the SDK, and how to join the final transcripts.
  • Recordings: Stream the file through the WebSocket or gRPC API with append fragments. Send the audio faster than real time, in parts of at most 16 MiB, as Transcribe a long recording describes.

Report a failure

Get the request ID from the stream, or from the error that it raised: Email support@rime.ai with:
  • the request ID and the UTC time of the failure
  • the error category and its message
  • the SDK and version, or the transport that you called directly
  • the audio format, and how your code ended the audio
Do not put your API key in the report.

Before production

  • Your API key is only on your backend.
  • You pin your SDK version, because the packages are in alpha.
  • Your code acts only on final transcripts.
  • You log the request ID of every stream.
  • Each stream opens when speech starts, and your backend sends silence during pauses.
  • You split long turns at pauses, and long recordings use append fragments.
  • Each error category has a handler, and each retry uses a new stream.
  • You set language from what you know about the speaker.