Errors
v4 uses the shared error rules (ERR-1 to ERR-6) unchanged and adds one: every operation documents every error it can return (V4-ERR-1). An error is written for the person or agent who has to act on it.
Problem JSON
Every 4xx and 5xx response is an RFC 9457
problem, served as application/problem+json and described by the shared
Problem schema:
Code
https://zup.fail/{slug} for a specific Zuplo error, or
https://zup.fail/http-status/{code} for a generic one (ERR-3).
The HTTP reason phrase, exactly. Never anything occurrence-specific (ERR-2).
The HTTP status code.
Written for people. It can be shown in the portal or by an agent as is. If the UI cannot show an API error, fix the API.
The path of the request.
On every error, and matches the request-id header (ROB-5).
Every invalid field on a validation failure, not only the first.
Code
Code
Code
Code
No stack traces, upstream errors or SQL.
Status codes
Malformed JSON, schema violations, cross-field rules ("a warn limit must be below
the block limit"), unknown query parameters, and a body field that names something
that does not exist (a poolId). All validation errors are 400.
Missing, invalid or expired credentials. Has WWW-Authenticate. Never used for
"not allowed".
Authenticated but not allowed (an OpenFGA denial). The detail names the missing
role.
The resource does not exist, or the caller has no access to the account it belongs to (masking, ERR-5).
With the current state: name already taken, resource still in use, or singleton already exists.
Has Retry-After.
No internal details. Quote trace.requestId to support.
Code
Code
One code to handle. v4 does not use 422.
Documented on every operation
Every operation documents the errors it can return, using the shared responses
in #/components/responses.
The shared rule (ERR-6) asks for 401 and default. v4 documents what the
operation can actually return, so agents and SDKs can plan error handling from the
spec:
| Operation | Documents |
|---|---|
| every operation | 401 403 429 default |
| the path has an ID | also 404 |
| there are query parameters or a body | also 400 |
Operations add other codes when they can occur. DELETE of a pool that still has
apps documents 409, for example, and so does creating a provider assignment,
whose label must be unique.
Code
Code
v4 error types
Generic conditions use https://zup.fail/http-status/{code}. Conditions that
clients act on get a registered slug in the shared catalog (@zuplo/errors):
https://zup.fail/no-access-{action}, for example no-access-edit-ai-pool.
The required responses, application/problem+json, the Problem schema, WWW-Authenticate and Retry-After.
The wording of title and detail.