> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modulate.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Common errors by category, with causes and fixes for auth, rate limits, audio validation, timeouts, and server errors.

Common errors organized by category, with causes and fixes.

## Authentication errors

### `401 Unauthorized`

**Cause:** No `X-API-Key` header was sent, or the header name is wrong.

**Fix:** Add the header to your request:

```bash theme={null}
curl -H "X-API-Key: your_api_key_here" ...
```

Check the exact casing: `X-API-Key`, not `x-api-key` or `Authorization`.

### `403 Forbidden` (REST)

Two different problems return `403`:

| Scenario | Response detail | Fix |
| - | - | - |
| The request is not permitted | `"This request is not permitted."` | Confirm the key is valid and active on the [API Keys page](https://platform.modulate.ai/dashboard/api-keys) |
| The model is not enabled for the organization | `"This API key does not have access to this model."` | Check the access on the [API Keys page](https://platform.modulate.ai/dashboard/api-keys), otherwise contact [support@modulate.ai](mailto:support@modulate.ai) |

### WebSocket close code `4001`

**Cause:** The `api_key` query parameter is missing or contains an invalid key.

**Fix:** Pass the key at connection time:

```text theme={null}
wss://platform.modulate.ai/api/velma-2-stt-streaming-english-v2?api_key=your_api_key_here&audio_format=ogg
```

### WebSocket close codes `4003` and `4004`

**Cause:** `4003` means the request is not permitted. `4004` means the key is valid but the model is not enabled for the organization.

**Fix:** Check [the limits specified for your API key](https://platform.modulate.ai/dashboard/api-keys); otherwise contact [support@modulate.ai](mailto:support@modulate.ai).

## Rate limit errors

### `429 Too Many Requests` (REST)

**Cause:** One of three limits. The `detail` field names which: `Concurrent request limit reached.`, `Insufficient credits.`, or `Monthly usage limit reached.` Only the concurrency limit clears on its own.

**Fix:** Retry the concurrency limit with exponential backoff and jitter. Return the other two without retrying:

```python theme={null}
import time, random, httpx

def post_with_retry(url, files, headers, max_retries=5):
    for attempt in range(max_retries):
        response = httpx.post(url, files=files, headers=headers)
        if response.status_code != 429:
            return response
        if not response.json().get("detail", "").startswith("Concurrent request limit"):
            return response  # credits or monthly limit: retrying does not clear it
        wait = (2 ** attempt) + random.uniform(0, 1)
        time.sleep(wait)
    return response
```

Persistent `429`s mean the traffic pattern exceeds the model's concurrency cap rather than spiking past it. Bound the work with a semaphore, or [contact us](/support#contact-us) to raise the cap. See [Limits](/guides/authentication#limits).

### WebSocket close codes `4029`, `4030`, and `4031`

**Cause:** `4030` means the model's concurrency cap is full. `4029` means insufficient credits. `4031` means the organization's monthly usage limit has been reached.

**Fix:** For a concurrency cap, reduce simultaneous connections and reconnect after a delay. For credits or a monthly limit, check the balance in the dashboard; a monthly limit does not clear until the next billing cycle unless it's raised. None of these resolve by retrying immediately.

## Audio validation errors

### `400 Bad Request`, unsupported format

**Cause:** The audio file format isn't supported by the endpoint you're calling.

| Endpoint | Common mistake | Fix |
| - | - | - |
| Velma Triage, Multilingual Transcription, Multilingual Fast Transcription, PII/PHI Redaction, Emotion Detection, Accent Detection, Audio Event Detection (batch) | Sending a file outside the 10 extensions these accept | Convert to one of `.aac`, `.aiff`, `.flac`, `.mov`, `.mp3`, `.mp4`, `.ogg`, `.opus`, `.wav`, `.webm` |
| Velma Triage, Multilingual Transcription, PII/PHI Redaction (streaming) | Sending `m4a`, `mp4`, `opus`, or another container outside the 7 these accept | Convert to `wav`, `mp3`, `ogg`, `flac`, `webm`, `aac`, `aiff`, or to raw PCM |
| Deepfake Detection, Music & Speech Detection, AI Music Detection, English Fast Transcription (streaming) | Sending an MP4-family value (`mp4`, `m4a`, `3gp`, …) in a non-streamable layout | Re-mux with a streamable (faststart) layout, or send raw PCM |
| Any streaming endpoint | Declaring a raw PCM `audio_format` while sending container bytes | Match the declared format to the bytes, or drop `audio_format` where the endpoint auto-detects |

The accepted set differs per endpoint. Each capability page lists its own in full.

### `422 Unprocessable Entity`

**Cause:** On Deepfake Detection, the audio is shorter than 0.5 seconds. On other endpoints, `422` means a required request field is missing or malformed, most often the `upload_file` part. Velma Triage also returns `422` for a malformed `config`, an unknown preset identifier, or a definition missing a required field.

Empty files, and files whose content is only metadata with no audio samples, also trigger this.

**Fix:** Verify the actual audio duration not just the file size. Silent files or files where the audio track was stripped can report a non-zero duration but contain no usable samples. Use ffprobe to inspect:

```bash theme={null}
ffprobe -v quiet -show_entries format=duration -of csv=p=0 yourfile.wav
```

### WebSocket close code `1003`, invalid query parameters

**Cause:** `audio_format`, `sample_rate`, or `num_channels` is missing, misspelled, or unsupported. On Deepfake Detection, Music & Speech Detection, AI Music Detection, and English Fast Transcription streaming, omitting `audio_format` alone triggers this, because those four require it on every connection.

**Fix:** Check that:

* `audio_format` is in the endpoint's accepted list. Each capability page states it.
* `sample_rate` is one of `8000`, `11025`, `16000`, `22050`, `32000`, `44100`, `48000`, `96000`, and is sent only with a raw format.
* `num_channels` is between 1 and 8, and is sent only with a raw format.

Sending `sample_rate` or `num_channels` for a container format is itself an error on the endpoints that reject it.

On English Fast Transcription (streaming), `1003` also covers `diarize`. An invalid value returns `Invalid diarize='yes'. Expected 'true' or 'false'.`, and `diarize=true` on an instance where speaker labelling is not enabled returns `diarize=true is not available on this endpoint.` Retrying does not clear the second one; reconnect without `diarize`.

### WebSocket close code `1013`, service temporarily at capacity

**Cause:** The service could not accept the connection. This is not an account or billing condition, so it is distinct from `4029`, `4030`, and `4031`.

**Fix:** Retry the connection. On English Fast Transcription (streaming), a `diarize=true` connection has a lower concurrency ceiling than plain transcription, so it can be refused while a plain connection to the same endpoint succeeds. If diarized connections are being refused under load, fall back to `diarize=false` rather than retrying the diarized connection indefinitely.

### WebSocket close code `4002`, audio could not be decoded

**Cause:** The audio could not be decoded, or the raw PCM bytes you're sending don't match the `audio_format`, `sample_rate`, or `num_channels` you declared at connection time.

**Fix:** If sending a container format (e.g. WebM, Ogg), make sure the stream is valid and not truncated. If sending raw PCM, confirm that your encoding pipeline produces exactly the format you declared. If you resampled to 16000 Hz but declared `sample_rate=44100`, the model will receive malformed frames.

## Timeout errors

### `504 Gateway Timeout`

**Cause:** Batch processing exceeded 60 seconds. This is uncommon for typical audio files but can happen with very long recordings or during periods of high server load. It can also happen if the file is above the maximum recommended file size of 100 MB.

**Fix:**

* Verify your file is within the recommended length range.
* Verify your file is under 100 MB.
* If the issue is persistent on files that should process quickly, email [support@modulate.ai](mailto:support@modulate.ai) with the file (if possible), the file type, file duration, file size, and endpoint.
* For long recordings, consider splitting into smaller chunks.

### English Fast Transcription timeouts

If `504` recurs on this endpoint, check that the file is not corrupted or padded with long stretches of silence, and that it is within the 100 MB limit.

## Server errors

### `502 Bad Gateway` (Multilingual Fast Transcription batch)

**Cause:** Transcription is temporarily unavailable.

**Fix:** Retry with exponential backoff. The response `detail` field is intentionally generic. If the error persists, email [support@modulate.ai](mailto:support@modulate.ai).

### `503 Service Unavailable`

**Cause:** The inference server is temporarily overloaded.

**Fix:** Retry with exponential backoff. Do not hammer the endpoint with immediate retries as this worsens the overload. See the retry pattern under [Rate limit errors](#429-too-many-requests-rest) above.

## Still stuck?

If none of the above matches your situation, email [support@modulate.ai](mailto:support@modulate.ai) with:

* Endpoint URL
* Full request headers (**redact your API key**)
* Response body and status code
* Audio format, duration, and file size


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.