CRUMB a card from devarno-cloud

Error Code to HTTP Status Mapping

so1 beginner 3 min read

ELI5

The error code is the colour on the label; the HTTP status is the post-office tier. Same letter, different envelopes — both must agree, otherwise the receiver can’t sort the mail.

Technical Deep Dive

Canonical Mapping

Per ADR-004:

CodeHTTPMeaning
UNAUTHORIZED401session invalid/missing
FORBIDDEN403authenticated but not permitted
BAD_REQUEST400malformed request (missing field)
VALIDATION_ERROR400typed validation failed (Zod)
NOT_FOUND404resource absent
CONFLICT409state conflict (Idempotency-Key mismatch — see so1-009)
GITHUB_ERROR502upstream GitHub failed
N8N_ERROR502upstream n8n failed
MCP_ERROR502MCP tool/server failed
INTERNAL_SERVER_ERROR500unhandled exception
SERVICE_UNAVAILABLE503dependency down (secrets, queue)

Selection Flow

flowchart TD
fail[failure detected] --> who{whose fault?}
who -- client auth missing --> u[UNAUTHORIZED 401]
who -- client auth ok, perm no --> f[FORBIDDEN 403]
who -- client payload bad --> kind{shape vs values?}
kind -- shape --> br[BAD_REQUEST 400]
kind -- values --> ve[VALIDATION_ERROR 400]
who -- not found --> nf[NOT_FOUND 404]
who -- state collision --> co[CONFLICT 409]
who -- upstream service --> svc{which?}
svc -- github --> ge[GITHUB_ERROR 502]
svc -- n8n --> ne[N8N_ERROR 502]
svc -- mcp --> me[MCP_ERROR 502]
who -- bff bug --> ise[INTERNAL_SERVER_ERROR 500]
who -- dependency down --> sa[SERVICE_UNAVAILABLE 503]

400 Variants Distinction

BAD_REQUEST is structural (missing field, wrong content-type). VALIDATION_ERROR is semantic (branch is present but not a valid git ref). Clients can show different remediation: “fix request shape” vs “fix this field”.

502 Choice for Upstreams

ADR-004 elects 502 (Bad Gateway) for all upstream failures because the BFF acts as the gateway. Clients can therefore retry with the same intent; the failure was not theirs.

Key Terms

  • Code → stable, machine-readable string from the canonical table.
  • HTTP status → tier-level signal carried in the response line.
  • Bad Gateway (502) → standard semantic for “I called somebody else and they failed me”.

Q&A

Q: A user lacks access to a GitHub repo — FORBIDDEN or GITHUB_ERROR? A: FORBIDDEN (403). The decision was made by the BFF’s RBAC, not relayed from GitHub. Use GITHUB_ERROR only when GitHub itself returned an error code.

Q: What status does a Zod validation throw produce? A: VALIDATION_ERROR with HTTP 400; the offending field path goes into error.details.

Q: Are 5xx codes safe for clients to retry? A: 502 and 503 are typically transient and retriable; 500 indicates a BFF bug — retry only with backoff and surface to engineering.

Examples

The GitHub adapter (so1-005) catches a 403 from api.github.com due to a revoked PAT. Because BFF authorization passed but the broker call failed, it raises GITHUB_ERROR (502) with details.upstream.statusCode=403not FORBIDDEN.

neighbors on the map