Errors

Hannu returns RFC 9457 problem+json — a stable code, a safe detail, and a request_id — so your agent can branch on the exact reason.

Every error is an RFC 9457 application/problem+json document. It names the exact control that failed with a stable machine code, so your agent can branch reliably instead of parsing prose.

The shape

JSON
{
  "type": "https://docs.hannu.africa/errors/insufficient_escrow_balance",
  "title": "Wallet balance is below the amount this task would lock",
  "status": 402,
  "code": "insufficient_escrow_balance",
  "detail": { "required": "303750", "available": "120000" },
  "request_id": "req_9c1"
}
  • code — the stable identifier to branch on. It never changes for a given condition.
  • title — the human-readable message for this occurrence. Read it for display, not for branching.
  • status — the HTTP status.
  • detail — a structured object of condition-specific fields (here, required and available), present only when the error carries specifics. Never contains PII or internal state. Read the numbers you need from it; read the human message from title.
  • request_id — quote this to support to trace any request.
Branch on code, not status

Several conditions share a status (three different 403s, for example). Always switch on code.

Handling patterns

  • rate_limited (429) — back off and retry after the Retry-After header.
  • idempotency_conflict (409) — you reused a key with a different body; use a fresh key.
  • insufficient_escrow_balance (402) — fund the wallet, then retry.
  • internal (500) — safe to retry; quote the request_id if it persists.

The full catalogue

Every code, its status, and its meaning is on the Errors reference.