HomeBlog → Transcription API errors and what they actually mean

Transcription API errors and what they actually mean

Published 2026-08-20 · 5 min read

Integrations break rarely and always at the worst moment. The good news: transcription errors come from a short list of causes and most take a minute to fix. Here they are in order, along with which ones deserve an automatic retry.

The status code table

CodeWhat happenedWhat to do
401Key is wrong, revoked or never arrivedCheck the Authorization header and the key itself
400File is empty, corrupt or not recognised as audioOpen it in a player, verify the codec
413File exceeds the size limitCompress to opus or split into parts
429Rate limit hit or balance exhaustedSlow down, or top up the balance
502Recognition backend temporarily unavailableRetry after a pause

The error body follows the familiar shape — an error object with message and type — so typed SDK exceptions keep working as they always did.

401 is usually the header

Three typical causes, in order of frequency:

The fastest check is a single curl call — if it succeeds, the problem is in your code, not your access.

429 means two different things

The same code arrives when you send requests too fast and when your paid minutes run out. The message text tells them apart. The first case is fixed with a queue and a concurrency cap, the second by topping up the balance.

A good habit: watch the remaining balance in the client area and set up a notification in advance, rather than discovering the problem in production logs.

How to retry properly

Only temporary failures are worth repeating: 429, 502 and network drops. A 400, 401 or 413 will return exactly the same answer forever — those need fixing, not hammering.

import time
from openai import OpenAI, APIStatusError, APIConnectionError

client = OpenAI(base_url="https://voicesscribe.com/v1", api_key="your key", max_retries=0)

def transcribe(path, tries=4):
    delay = 2
    for attempt in range(tries):
        try:
            with open(path, "rb") as f:
                return client.audio.transcriptions.create(model="whisper-1", file=f).text
        except APIStatusError as e:
            if e.status_code not in (429, 500, 502, 503):
                raise
        except APIConnectionError:
            pass
        time.sleep(delay)
        delay *= 2
    raise RuntimeError("could not transcribe " + str(path))

Doubling the delay matters more than the number of attempts: it gives the service room to recover and keeps you from hitting the same limit a second later.

Try it on your own recordings. Sign-up takes a minute, and the free minutes are enough to judge the quality.

Get a free API key

Frequently asked questions

Are minutes charged for failed requests?

No. Only successfully processed requests are billed; errors consume nothing.

Why do I get 400 on a file that plays fine?

Usually a renamed file: the extension says mp3 but the container is something else. Check with ffprobe and re-encode if needed.

How do I tell a rate limit from an empty balance?

By the message in the response body. The remaining balance and the deduction history are always visible in the client area.

Should I enable the SDK's built-in retries?

Usually not. Your own retry logic is safer because you decide which codes to repeat and how long to wait.

Related reading