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:
Go and Rust error names
Go and Rust error names
WebSocket upgrade refusals
WebSocket upgrade refusals
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:- 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.
- 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.
- 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.
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.
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
IfRIME_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 HTTP401, 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:- Language. Speech in a language other than the one that you selected returns a poor transcript, not an error.
- 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_formatto the rate and channel count of your capture. - Silence. An empty final transcript is a successful result for audio with no recognizable speech.
- 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 gRPCTranscribe 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
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
languagefrom what you know about the speaker.

