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.