Error Model (canonical error envelope)
errors specs/errors/model.kmd
O envelope canônico, máquina-legível, de um erro na Koder Stack: os campos obrigatórios (dados mínimos exigíveis) e opcionais (dados complementares) de um objeto de erro, as regras para preencher os complementares, e o mapeamento para resposta HTTP (problem+json) que todo backend Koder emite e todo cliente parseia. É o contrato SÍNCRONO de erro entre serviços e clientes — distinto da telemetria assíncrona de `specs/errors/reporting.kmd` (que vai pro reporter) e do texto humano de `user-facing-messages.kmd`. Classes/severidade/retryability vêm de `specs/errors/taxonomy.kmd`.
When this pattern applies
Primary triggers
- Emitir ou consumir uma resposta de erro de API entre componentes Koder
All triggers
- Desenhar/retornar uma resposta de erro de API (HTTP/RPC) em serviço Koder
- Parsear um erro vindo de um serviço Koder no cliente (app/SDK/CLI)
- Definir o struct/objeto de erro que cruza um boundary entre componentes
Specification body
Spec — Error Model (canonical envelope)
O shape de um erro que cruza um boundary (API HTTP/RPC, IPC, SDK). Vocabulário (classe/severidade/retryable) é
specs/errors/taxonomy.kmd. Texto humano éuser-facing-messages.kmd. Telemetria pro reporter éreporting.kmd. Esta spec é a fonte única do envelope síncrono.
Applicability
Toda resposta de erro que um componente Koder devolve a um chamador no
momento da falha — respostas HTTP/RPC de serviços backend, erros de IPC
(specs/ipc/protocol.kmd), erros propagados por bindings SDK. Não se
aplica a erro internal entre funções de um mesmo processo (isso é idiom de
linguagem — code/error-handling.kmd), nem ao payload de telemetria
enviado ao reporter (reporting.kmd).
Distinção crítica. Há três payloads de erro distintos, com donos distintos — não confundir:
Payload Quando Dono Envelope (esta spec) Síncrono, no momento da falha, serviço→cliente model.kmdTelemetria (Groups A–G) Assíncrono, depois, app→reporter.koder.dev reporting.kmdBloco de suporte (texto copiável) Manual, usuário→suporte user-facing-messages.kmd §5
R1 — Campos obrigatórios (dados mínimos exigíveis)
Todo envelope de erro deve conter, no mínimo:
| Campo | Tipo | Origem / regra |
|---|---|---|
error_id | string | Formato <PRODUCT>-<CATEGORY>-<CODE>-<SEQ> (user-facing-messages.kmd §4) |
error_category | string(2) | Enum fechado de taxonomy.kmd §R1 |
code | string | CODE do Error ID (HTTP status ou numérico do produto) |
severity | string | Enum de taxonomy.kmd §R3 |
retryable | bool | Classificação de taxonomy.kmd §R4 (conditional → false + recovery) |
message | string | Mensagem técnica verbatim (não humanizada; ver R4) |
occurred_at | string | ISO 8601 com timezone (2026-04-17T15:42:30-03:00) |
Esses sete são o contrato mínimo: um cliente pode decidir retry, exibir, logar e correlacionar com apenas eles.
R2 — Campos opcionais (dados complementares)
Incluídos quando disponíveis e quando R3 (regras de registro) permite:
| Campo | Tipo | Conteúdo |
|---|---|---|
request_id | string | Trace ID da requisição (correlação com log/trace — observability-first.kmd) |
cause | object | Erro encadeado da camada inferior, mesmo schema (recursivo); espelha o wrapping de error-handling.kmd §R1 |
http_status | int | Status HTTP, quando aplicável |
upstream_dependency | string | Serviço cuja falha originou este erro |
recovery | string | Ação que torna um conditional retryable ("re-authenticate", "free_space", "fix_field:cpf") |
context | object | Pares chave-valor do que se tentava ({"operation":"download","resource":"koder-hub@1.8.2"}) |
fields | array | Para VL: lista de {field, rule, message} (ver specs/data/validation.kmd) |
doc_url | string | URL de documentação do erro (quando o produto a publica) |
R3 — Regras para registro de dados complementares
- Mínimo sempre presente — nenhum campo de R1 é omissível; ausência é violação de contrato (audit R7.1).
- PII nunca no envelope — o envelope cruza a rede e pode ser logado.
Aplicam-se as mesmas proibições de
reporting.kmd §7e a higiene deerror-handling.kmd §R8: sem nome/email/CPF/token/path-com-username emmessage,context,causeoufields. Redigir antes de serializar. causeé finito — profundidade máxima 5; além disso, truncar e marcar"cause_truncated": true. Evita envelopes recursivos gigantes.contexté small + estável — chaves de um conjunto conhecido por produto; sem dumps de payload, sem valores de variáveis locais (error-handling.kmd §R8proíbe variable capture sem amendment).recoveryobrigatório quandoretryable == falseporconditional— um erro condicionalmente recuperável deve dizer como recuperar; senão o cliente não distingue denot-retryable.fieldsobrigatório paraerror_category == "VL"— validação sem o detalhe por-campo é inútil pro cliente corrigir (cross-linkspecs/data/validation.kmd §R-erros).
R4 — Relação com texto humano
- O envelope carrega mensagem técnica, nunca a humanizada. A humanização
é responsabilidade do cliente, via
user-facing-messages.kmd(o humanizer mapeiaerror_category+code→ template humano). - Um serviço não envia texto pt-BR/en-US "pronto pra UI" no
message— isso acoplaria backend a locale do cliente. O backend mandaerror_category/code/message técnico; o cliente decide o texto. - O
error_idé a cola: aparece no envelope (R1), no log do servidor (user-facing-messages.kmd §6), na telemetria (reporting.kmdGroup D) e no bloco de suporte (user-facing-messages.kmd §5).
R5 — Mapeamento HTTP (problem+json)
Respostas de erro HTTP usam application/problem+json
(RFC 9457) com extensões Koder.
O status HTTP é o http_status; os campos Koder são membros de extensão.
HTTP/1.1 503 Service Unavailable
Content-Type: application/problem+json
{
"type": "https://errors.koder.dev/DL/503",
"title": "Service Unavailable",
"status": 503,
"detail": "download token service temporarily unavailable",
"error_id": "HUB-DL-503-001",
"error_category": "DL",
"code": "503",
"severity": "error",
"retryable": true,
"occurred_at": "2026-04-17T15:42:30-03:00",
"request_id": "req-9f2a…",
"upstream_dependency": "token-service"
}
Mapeamento RFC 9457 ↔ Koder:
| RFC 9457 | Koder | Nota |
|---|---|---|
status | http_status | Idêntico; status é o membro padrão |
title | — | Curto, estável por code (não localizar) |
detail | message | Mensagem técnica desta ocorrência |
type | derivado | https://errors.koder.dev/<CATEGORY>/<CODE> |
instance | request_id | Quando disponível |
error_id, error_category, code, severity, retryable, occurred_at,
cause, recovery, context, fields são membros de extensão Koder.
Para gRPC/RPC não-HTTP: mesmos campos como metadata/trailer;
http_statusvira o status-code equivalente do transporte (verspecs/ipc/protocol.kmd).
R6 — Implementação (SDK-first)
- O envelope é construído e parseado pelo
engines/sdk/koder_kit(KoderError/KoderErrorEnvelope), nunca remontado à mão por produto (policies/sdk-first.kmd). - Backends Go: middleware de boundary (
error-handling.kmd §R3) converte o erro internal → envelope na borda do handler. Um único helperkoderhttp.WriteError(w, err)serializa em problem+json. - Clientes:
koder_kitexpõeparseError(response) → KoderErrorcom os campos de R1 garantidos e os de R2 opcionais.
R7 — Audit determinístico
error-model-audit.sh (advisory), via /k-housekeep:
- Resposta de erro de serviço Koder sem um dos 7 campos de R1 → error.
Content-Typede erro HTTP ≠application/problem+json→ warning.message/context/causecasando regex de PII (email/CPF/token) → error.error_category == "VL"semfields→ warning.retryable == falsecom hint de condicionalidade nomessagemas semrecovery→ warning.- Texto localizado (pt-BR/en-US) detectado em
message→ warning (texto humano pertence ao cliente, R4).
Cross-link
specs/errors/taxonomy.kmd— defineerror_category,severity,retryable.specs/errors/user-facing-messages.kmd— Error ID (§4) + humanização (cliente).specs/errors/reporting.kmd— telemetria assíncrona (payload distinto).specs/code/error-handling.kmd—§R1(cause chain),§R3(boundary),§R8(PII).specs/data/validation.kmd— origem do arrayfieldsem errosVL.specs/ipc/protocol.kmd— envelope sobre IPC não-HTTP.
References
specs/errors/taxonomy.kmdspecs/errors/user-facing-messages.kmdspecs/errors/reporting.kmdspecs/code/error-handling.kmdspecs/ipc/protocol.kmdspecs/errors/README.kmd