Error format
z4j errors are returned as a small JSON envelope. The brain does not emit RFC 7807 Problem Details.
{ "error": "validation_failed", "message": "request body failed validation (2 field(s))", "request_id": "01H...", "details": { "errors": [ {"loc": "body.email", "type": "value_error.email"}, {"loc": "body.role", "type": "enum"} ] }}| Field | Meaning |
|---|---|
error | Stable short identifier. Branch on this from API clients. |
message | Human-readable summary. Operator-friendly English; do not parse. |
request_id | The same value as the X-Request-Id response header. Quote it when filing a bug. |
details | Per-error context. For validation failures this is {"errors": [{"loc": "...", "type": "..."}, ...]}. The offending input value is deliberately not echoed — it may contain caller-supplied secrets. |
HTTP status mapping
Section titled “HTTP status mapping”The brain raises typed Z4JError subclasses; the error middleware maps them to HTTP status codes:
| Status | Exception class | Typical error codes |
|---|---|---|
| 401 | AuthenticationError, SignatureError | invalid_credentials, session_expired, signature_invalid |
| 403 | AuthorizationError | insufficient_role, policy_violation |
| 404 | NotFoundError | not_found |
| 409 | ConflictError | conflict_duplicate_name, conflict_state |
| 422 | ValidationError, InvalidFrameError, Pydantic validation | validation_failed, invalid_frame |
| 426 | ProtocolError | protocol_upgrade_required |
| 429 | RateLimitExceeded | rate_limited |
| 502 | AdapterError | adapter_error |
| 503 | AgentOfflineError | agent_offline |
| 504 | CommandTimeoutError | command_timeout |
| 500 | everything else | internal_error (with request_id for log correlation; the exception class name is deliberately not surfaced) |
Tracing
Section titled “Tracing”Every response includes an X-Request-Id header. The value is also in the JSON body as request_id. Pass it when filing a bug or scanning logs.
Audit trail for denials
Section titled “Audit trail for denials”Denials and validation failures on schedule endpoints leave an audit-log breadcrumb so IDOR-enumeration attempts have a forensic trail. The audit row is HMAC-chained; structured log lines alone are not tamper-evident.