Error Codes
This page lists the errors you can run into when calling the Cochl.Sense Cloud API — both errors returned immediately when a request is rejected, and errors that show up later inside a completed analysis job. If you’re using the official Python library (cochl), see §6 for how these appear as exceptions.
1. Two places errors come from
The most important thing to understand about this API’s errors is when they happen:
| When | How it’s delivered | |
|---|---|---|
| ① Request errors (synchronous) | The moment you send the request | Auth, option, or file problems. For project-key requests (§3), always a non-200 HTTP status code. For Speaker Recognition (§5), only auth failures use a status code (401) — business-rule violations return HTTP 200 with the error in the response body instead. |
| ② Analysis errors (asynchronous) | After the request is accepted, during background processing | analyze / analyze_file accept the request and immediately return a job_id; analysis then runs in the background. Problems in the analysis engines don’t come back as HTTP errors — they show up inside the job result, per service. (§4) |
Response body shapes
The shape of the error body depends on which kind of error it is — worth knowing before you write a parser:
| Error type | HTTP | Body shape |
|---|---|---|
| General error | 400 / 401 / 402 / 404 | {"error": "<message>"} |
| Request validation failure | 422 | {"error": "Validation error", "details": [ ... ]} |
| Internal server error | 500 | Internal Server Error — plain text, not JSON. Parsing it as {"error": ...} will fail. |
Speaker Recognition API (/api/v2) | 200 / 401 / 502 | {"data": null, "error": "<message>", "debug": "<...>"} |
2. Authentication keys
| Key | Header | Used for |
|---|---|---|
| Project Key | X-Api-Key | Audio analysis (IntegratedApi) — Sound Event Detection / Speech Analysis / Audio Insights |
| Organization Key | X-Org-Key | Speaker registration & recognition (SpeakerProfileApi) |
A project key doesn’t expire on its own — issuing a new one just invalidates the old one, and a request made with an invalidated key gets Invalid API key. Key validation results are cached for up to 10 minutes, so a key change can take up to 10 minutes to take effect.
3. Request errors (synchronous — Project Key)
These are HTTP errors returned by POST /api/v1/analyze and POST /api/v1/analyze_file at the moment the request is accepted or rejected.
| Situation | HTTP | Response body |
|---|---|---|
| Key missing (header absent/empty) | 401 | {"error":"API key required"} |
| Key invalid (typo, revoked, deleted) | 401 | {"error":"Invalid API key"} |
| No analysis service enabled | 400 | {"error":"No services selected"} |
audio_insights enabled without both sound_event_detection and speech_analysis | 400 | {"error":"audio_insights requires both speech_analysis and sound_event_detection to be true"} |
audio_insights and caption don’t match | 400 | {"error":"audio_insights and caption must be both true or both false"} |
speaker_profile enabled without speech_analysis | 400 | {"error":"speaker_profile requires speech_analysis: true"} |
translation enabled without speech_analysis | 400 | {"error":"translation requires speech_analysis: true"} |
| Undefined option key sent (e.g. a retired field name) | 422 | {"error":"Validation error","details":[{"type":"extra_forbidden","loc":["body","options","<field>"], ...}]} |
Required field missing (e.g. samplerate) | 422 | {"error":"Validation error","details":[{"type":"missing","loc":["body","<field>"], ...}]} |
| Unsupported or corrupted audio file (decode failure) | 500 | Internal Server Error (plain text) |
Invalid base64 audio data (/analyze only) | 500 | Internal Server Error (plain text) |
| Free-tier usage limit exceeded | 402 | {"error":"exceeded maximum usage limit"} |
| Path doesn’t exist | 404 | {"error":"Not Found"} |
| Internal error during key verification | 500 | {"error":"API key verification failed"} |
On success, both endpoints return 200 with {"job_id": "...", "status": "accepted", "created_at": "..."}. Analysis then continues in the background — see §4.
4. Service errors inside job results (asynchronous)
Because analyze / analyze_file return 200 accepted as soon as the request is queued, problems in the analysis engines (ASR, Sound Event Detection, Caption) aren’t HTTP errors — they appear inside the job result once you fetch it. GET /api/v1/jobs/{job_id} returns HTTP 200 even when a service failed; only that service’s entry is marked status: "error" (other services that succeeded still return their results — partial success is normal).
GET /api/v1/jobs/{job_id} -> HTTP 200
{
"job_id": "b8cbefce-...",
"status": "completed",
"result": {
"sound_event_detection": { "status": "error", "error": "max_workers must be greater than 0" },
"speech_analysis": { "status": "error", "error": "ASR Engine API error: 500" },
"caption": { "status": "error", "error": "Caption API error: 500" }
}
}
| Cause | error string |
|---|---|
| ASR engine returned an error response (3xx or higher) | ASR Engine API error: <status code> |
| ASR engine call failed (timeout, network) | The raw exception message |
| Caption engine returned an error response (3xx or higher) | Caption API error: <status code> |
| Internal engine processing error (an observed real case) | max_workers must be greater than 0 |
Always check each service’s status field — a completed job is not the same as a fully successful one.
5. Speaker Recognition errors (Organization Key — /api/v2)
The Speaker Recognition API (used by SpeakerProfileApi) always wraps its response in a {data, error, debug} envelope. Authentication failures return 401; everything else — business-rule violations — return HTTP 200 with an error field (kept for compatibility with the legacy SR server).
| Situation | HTTP | Response body |
|---|---|---|
| Organization key missing (header absent) | 401 | {"data":null,"error":"x_org_key required","debug":""} |
| Organization key invalid (not registered) | 401 | {"data":null,"error":"organization not found","debug":""} |
| Speaker name violates naming rules (letters, numbers, underscore only) | 200 | {"data":null,"error":"speaker is invalid. only alphabet, number and underscore are allowed","debug":""} |
| Voice file missing on registration | 200 | {"data":null,"error":"file is required","debug":""} |
| Empty file uploaded | 200 | {"data":null,"error":"an empty file","debug":""} |
| Audio file longer than 10 minutes | 200 | {"data":null,"error":"audio length is longer than 10 minutes","debug":""} |
Voice file exceeds 10 MB (blocked client-side by SpeakerProfileApi before the request is sent) | — | CochlSenseException: one of files is bigger than 10.0 MB / file is bigger than ... MB |
| Voice file exceeds 100 MB (server-side cap — reachable if calling the raw HTTP API directly) | 200 | {"data":null,"error":"one of uploaded files is bigger than 100 MB","debug":""} |
| Organization already has 50 registered speakers | 200 | {"data":null,"error":"speaker_max_count(50) exceeded","debug":""} |
| Speaker engine unreachable | 502 | {"data":null,"error":"speaker service unavailable" / "recognition service unavailable","debug":""} |
Voice files are limited to 10 MB and 10 minutes each (the library blocks oversized files before sending; the server separately enforces a 100 MB hard cap). Each speaker supports up to 20 voice samples (5–20 recommended for accuracy — no confirmed error message exists yet for exceeding this). An organization can register up to 50 speakers in total.
6. Errors in the Python library (cochl 2.0.1)
Most users call this API through the official Python library rather than raw HTTP. The exceptions it actually raises can differ from the raw API response above, so they’re listed separately.
CochlSenseException inherits from BaseException, not Exception — a bare except Exception: will not catch it. You must catch CochlSenseException explicitly.6.1 IntegratedApi (audio analysis — Project Key)
When a request fails (any non-2xx response), the library discards the server’s detailed message and uses only the HTTP reason phrase as the exception message. For example, the server’s Invalid API key becomes just Unauthorized. Every such exception is a CochlSenseException, and its message always has "Please contact support@cochl.ai" appended.
| Situation | API response | Library exception |
|---|---|---|
| Invalid project key | 401 Invalid API key | CochlSenseException: Unauthorized |
| Unsupported format, corrupted file, or invalid base64 | 500 Internal Server Error | CochlSenseException: Internal Server Error |
| No service selected, or an invalid option combination | 400 (detailed message) | CochlSenseException: Bad Request |
| Free-tier usage limit exceeded | 402 exceeded maximum usage limit | CochlSenseException: Payment Required |
| Object created with an empty project key | (before the request is sent) | ValueError: invalid project key "" |
| An individual analysis service failed | 200 (inside the result — see §4) | No exception raised — check result["<service>"]["status"] == "error" yourself |
get_completed_result(job_id) returns None, without raising an exception, if the analysis failed or the underlying stream timed out. Always check the return value before using it.6.2 SpeakerProfileApi (speaker registration & recognition — Organization Key)
Because Speaker Recognition’s business-rule violations come back as 200 + error, the library passes the server’s actual message straight through. Authentication failures (401) are the one exception — those still collapse to the reason phrase, same as IntegratedApi.
| Situation | Library exception / result |
|---|---|
| Invalid organization key | CochlSenseException: Unauthorized |
| Speaker name violates naming rules | CochlSenseException: speaker is invalid. only alphabet, number and underscore are allowed |
| Uploaded file exceeds 10 MB (blocked client-side before the request) | CochlSenseException: file is bigger than ... MB |
| Object created with an empty organization key | ValueError: invalid project key "" |
6.3 Recommended error-handling pattern
from cochl.sense import IntegratedApi, IntegratedApiOptions
from cochl.sense.exception import CochlSenseException
from cochl.sense.http_request import HttpRequestException
import urllib.error
api = IntegratedApi("YOUR_PROJECT_KEY")
try:
job = api.analyze_file(
"audio.wav",
IntegratedApiOptions(sound_event_detection=True),
)
result = api.get_completed_result(job["job_id"])
if result is None:
# Analysis failed, or the stream timed out — not an exception
print("analysis did not complete")
else:
sed = result.get("sound_event_detection", {})
if sed.get("status") != "success":
print("SED failed:", sed.get("error"))
except CochlSenseException as e: # inherits BaseException — must be explicit
print("API error:", e.message) # e.g. Unauthorized / Bad Request / Internal Server Error
except HttpRequestException as e: # empty file / connection failure
print("request error:", e.message)
except FileNotFoundError as e: # missing file
print("file not found:", e)
except urllib.error.HTTPError as e: # unknown job_id in get_completed_result
print("job not found:", e.code)
Even if you keep a catch-all except Exception: as a safety net, put except CochlSenseException: before it — otherwise API errors go uncaught and the program exits.
6.4 Legacy Client (EventDetectionApi, v1.x)
Client is the legacy v1.x Sound Event Detection-only client (api.cochl.ai/sense, not the Integration API). New integrations should use IntegratedApi (§6.1) instead.| Situation | Exception | Message |
|---|---|---|
| Empty/missing project key | ValueError | invalid project key "" |
| File doesn’t exist | FileNotFoundError | the file path |
| Unsupported format (not mp3/wav/ogg) | ValueError | invalid file format "...", supported formats: ['mp3', 'wav', 'ogg'] |
| API request failed | CochlSenseException | HTTP reason phrase, or the server’s error message |
| Server-side analysis error | CochlSenseException | the server’s error message |
predict(timeout=N) exceeded | TimeoutException (also BaseException, not Exception) | Prediction (session_id=...) has timed out "Ns" |
7. Rate limits & audio length
There is currently no request-rate limit — sending requests in a burst won’t get you a 429. Under heavy load, requests may instead hit downstream timeouts (ASR: 30s, Caption: 120s) and surface as a service error in the job result (§4).
The API and the Python library have no server-side audio length limit. The 1-hour cap only applies to the web Dashboard. A very long file sent via the API can still fail — not from a length check, but from processing taking long enough to hit the downstream timeouts above.
See also
- Custom Sound: Speaker Profile—registering and recognizing speakers; see §5 above for its error cases
- Getting Started—setup and your first request
- Sound Event Detection—detection details and service options referenced in §3