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"}
]
}
}
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.

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)

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.