Skip to content

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"}
]
}
}
FieldMeaning
errorStable short identifier. Branch on this from API clients.
messageHuman-readable summary. Operator-friendly English; do not parse.
request_idThe same value as the X-Request-Id response header. Quote it when filing a bug.
detailsPer-error context. For validation failures this is {"errors": [{"loc": "...", "type": "..."}, ...]}. The offending input value is deliberately not echoed — it may contain caller-supplied secrets.

The brain raises typed Z4JError subclasses; the error middleware maps them to HTTP status codes:

StatusException classTypical error codes
401AuthenticationError, SignatureErrorinvalid_credentials, session_expired, signature_invalid
403AuthorizationErrorinsufficient_role, policy_violation
404NotFoundErrornot_found
409ConflictErrorconflict_duplicate_name, conflict_state
422ValidationError, InvalidFrameError, Pydantic validationvalidation_failed, invalid_frame
426ProtocolErrorprotocol_upgrade_required
429RateLimitExceededrate_limited
502AdapterErroradapter_error
503AgentOfflineErroragent_offline
504CommandTimeoutErrorcommand_timeout
500everything elseinternal_error (with request_id for log correlation; the exception class name is deliberately not surfaced)

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.

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.