Errors
Errors are JSON objects with a stable machine‑readable error code. Match on the
code, not the HTTP status or human message.
Shape
{ "error": "validation_error", "issues": [{ "path": "title", "message": "Required" }] }Most errors are just { "error": "<code>" }; some add context fields (issues,
message, entitlement fields, path).
Status → meaning
| Status | When |
|---|---|
400 | Validation failed (validation_error / Fastify validation_failed), malformed body (invalid_json), or a bad request shape |
401 | No / invalid credentials (unauthorized, missing_bearer_token, invalid_bearer_token) |
403 | Authenticated but not entitled (entitlement_required) or access denied / access code required |
404 | Resource not found, or an owner mismatch that resolves to “not found” |
405 | method_not_allowed on a resource that exists |
409 | Conflict — library_name_conflict, track_set_mismatch, delete‑original, duplicate |
422 | Structural validation — e.g. split_sheet_structural_validation_failed |
429 | Rate limited — analytics_rate_limited |
500 | Unhandled error (Fastify collapses to internal_error; never leaks the message) |
501 | native_route_not_implemented (native handler missing and proxy disabled) |
502 | Provider error — analytics_provider_error, AI provider failure |
503 | Dependency unavailable — <x>_database_unavailable, native_runtime_required, provider not configured |
Common codes by area
| Code | Status | Meaning |
|---|---|---|
unauthorized | 401 | No resolvable actor |
entitlement_required | 403 | Plan/feature gate — body carries feature, limit, current, planId, upgradeRequired |
validation_error | 400 | Request failed its Zod schema; issues[] lists { path, message } |
invalid_json | 400 | Body wasn’t valid JSON |
*_not_found | 404 | e.g. track_not_found, pack_not_found, peaks_not_found, pack_link_not_found |
track_resource_not_found | 404 | Unknown :resource on a track sub‑route |
method_not_allowed | 405 | e.g. PUT on a track resource other than lyrics/split-sheet |
track_set_mismatch | 409 | Reorder payload doesn’t match the pack’s track set |
library_name_conflict | 409 | Library name already used |
split_sheet_structural_validation_failed | 422 | Split‑sheet totals/structure invalid |
downloads_disabled | 403 | Share settings disallow downloads on that pack link |
access_code_required | 403 | Pack link needs an access code |
analytics_rate_limited | 429 | Dub analytics per‑second limit hit |
analytics_provider_error | 502 | Dub returned an error |
*_database_unavailable | 503 | DB pool unavailable (and proxy fallback disabled) |
native_runtime_required | 503 | Endpoint is native‑only; runtime isn’t Vercel |
native_route_not_implemented | 501 | No native handler and proxy fallback disabled |
Validation errors are the most common during integration. Inspect issues[] —
each entry’s path points at the offending field and message explains the
rule (from the Zod schema). See Data Contracts.