Skip to main content
The SDK returns one of two structured envelopes for every failure: a ValidationError for request-shape failures (HTTP 400) and a generic Error for everything else. Both shapes are declared in the bundled OpenAPI spec.

Validation errors (HTTP 400)

When a request fails buf.validate checks or has malformed JSON, the response is:
Branch on the HTTP status (400) and surface violations to the developer. End users almost never see these — they indicate a client-side bug.

Other errors (everything except 400)

For any non-validation failure, the response is a minimal envelope:
message is the only field. Treat it as developer-facing detail; it may include internal context. The discriminator for branching is the HTTP status code, not a field inside the body:

Batch errors

BatchGetSongs, BatchGetAlbums, BatchGetArtists, BatchGetShows, BatchGetMovies, BatchGetSeasons, and BatchGetEpisodes return a map of ID → result, where each entry is a oneof of either the entity or a BatchItemError. Successful and failed items live side by side in the same response — the top-level call only fails if the request itself is malformed.
BatchItemError carries code (an ErrorCode enum string — typically ERROR_CODE_NOT_FOUND or ERROR_CODE_PERMISSION_DENIED) and message. Iterate the map, branch on which oneof arm is set, and only fail your overall flow if the failures violate your business rules.

Idempotency and retries

  • All Get*, Batch*, Search, and Browse* operations are idempotent — safe to retry on INTERNAL / UNAVAILABLE.
  • Acquire*Stream is idempotent within the duration of a stream URL — retrying simply returns a fresh URL. Each acquire is the billable event, so don’t retry past the back-off window unnecessarily.
  • CreateApiKey, RotateApiKey, RevokeApiKey are not safely retryable on ambiguous failures. Use ListApiKeys to reconcile state before retrying.