Skip to main content

Errors and retries

Things break. Good API clients make that boring: read the status, keep the request_id, and retry only when the failure is actually temporary.

Core error envelope​

Authentication, model, rate-limit, and service failures use this shape:

{
"error": {
"message": "Invalid API key.",
"type": "authentication_error",
"param": null,
"code": "invalid_key"
},
"request_id": "<request-id>"
}

Use error.code for program logic, show or log error.message, and retain the request_id for support.

KittenML gateway validation errors, including unsupported TTS output formats, use the same structured envelope:

{
"error": {
"message": "Unsupported response_format. Supported formats: mp3, opus, aac, flac, wav, pcm.",
"type": "invalid_request_error",
"param": "response_format",
"code": "invalid_response_format"
},
"request_id": "<request-id>"
}

Parameter-validation errors returned with status 422, and rare failures originating inside the speech generator, can use a top-level detail string or array. Clients should therefore handle both documented shapes for TTS 422 and 500 responses.

Status codes​

StatusMeaningClient action
400Invalid body, field, audio, or realtime eventCorrect the request; do not retry unchanged
401Missing, malformed, invalid, expired, revoked, or incorrectly scoped keyReplace or update the key
402Insufficient credit or suspended billing stateResolve billing or account state
404Wrong path or unsupported modelCheck the URL and model ID
413Request or file exceeds an endpoint limitReduce or split the input
422TTS parameter validation failedCorrect the named field
429Account or migrated-key concurrency limit reached, or voice cloning momentarily busyRespect Retry-After when present; retry with backoff and jitter
502Inference service failedRetry with capped exponential backoff
503Authentication, billing, or inference service unavailableRetry with capped exponential backoff
Other 5xxUnexpected server failureRetry a limited number of times

Common error codes​

CodeMeaning
missing_api_keyThe bearer credential is absent
malformed_keyThe credential does not have a valid KittenML key shape
invalid_keyThe credential is unknown, revoked, or otherwise invalid
scope_not_allowedThe key lacks the permission required by the endpoint
insufficient_credit or out_of_creditsPaid ASR cannot begin with the available balance
invalid_fileThe upload is empty, oversized, or cannot be decoded
invalid_response_formatThe requested transcription representation or speech output format is unsupported
rate_limit_exceededThe applicable concurrency pool is full
custom_voice_creation_busyToo many voice clones are in progress; the request was not queued or waited too long
billing_service_unavailableAuthentication or paid-usage state cannot be checked temporarily
tts_service_unavailableSpeech generation is temporarily unavailable

Other endpoint-specific codes can be returned. Use the HTTP status for the broad error class and error.code for specific handling.

WebSocket errors​

Realtime authentication and admission failures arrive as a structured error event after the WebSocket upgrade, followed by a close frame:

{
"type": "error",
"error": {
"type": "authentication_error",
"code": "invalid_key",
"message": "Invalid API key."
},
"request_id": "<request-id>"
}

The close code differs by route: realtime STT (/v1/realtime and its /v1/stt/realtime alias) closes with 1000, while incremental-input TTS (/v1/tts/realtime) closes with 1008. Always use error.code to classify the failure; the close code is only a transport-level signal that the session ended.

Retry safely​

For retryable HTTP failures, use capped exponential backoff with random jitter. Limit the number of attempts, set a request timeout, and honor Retry-After when the response includes it. Do not retry an unchanged request for a status listed above as a client or account error.

A fresh client retry is a new inference request. If both the original and the retry succeed, both may be processed and recorded separately.