Códigos de erro
Todo erro compartilha um envelope: um código legível por máquina, uma mensagem legível por humanos no idioma de quem chama, detalhes por campo para falhas de validação, e um identificador de rastro.
Ramifique pelo código. A mensagem é texto de exibição e pode ser reescrita ou traduzida; o código é um identificador estável.
O envelope
Todo erro que a plataforma devolve tem este formato:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{ "field": "lei",
"code": "errors.LEI_FORMAT",
"message": "Legal Entity Identifier must be 20 characters",
"ruleType": "regex",
"severity": "error" },
{ "field": "address.state",
"code": "REQUIRED",
"message": "State is required when the country is US",
"ruleType": "cross_field",
"severity": "warning" }
],
"traceId": "550e8400-e29b-41d4-a716-446655440000"
}
}
details é preenchido em falhas de validação e é o que permite a um cliente pôr
cada mensagem sob o campo que a causou, em vez de mostrar um único aviso para um
formulário com dois problemas. Note que field usa o caminho pontuado para um
sub-campo composto — address.state, não state.
Falhas conduzidas por regra carregam ainda ruleType e severity, então um
cliente distingue um erro bloqueante de um aviso registrado sem tabela de
consulta.
Erros que não são por campo trazem details vazio e dependem do código:
{
"error": {
"code": "ENTITY_ALREADY_MERGED",
"message": "This entity has been merged into another",
"details": [],
"traceId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}
}
O traceId é gerado por requisição. Cite-o ao relatar um problema — ele localiza
a requisição exata nos logs.
Situações
| Situação | Significa | Faça |
|---|---|---|
| 400 | Requisição malformada ou inválida | Corrija a requisição. details nomeia cada campo problemático. |
| 401 | Não autenticado, ou sessão revogada (SESSION_REVOKED) | Entre novamente. Não há fluxo de renovação. |
| 403 | Autenticado mas não autorizado | Veja abaixo — a causa difere por código |
| 404 | Não encontrado | O recurso não existe, foi excluído, ou pertence a outra organização |
| 409 | Conflito | Restrição de unicidade. Mude o valor conflitante. |
| 413 | Payload grande demais | Reduza o corpo da requisição |
| 422 | Bem formada, mas viola uma regra de negócio | Leia a mensagem — ela declara a regra |
| 429 | Requisições demais | Tente de novo após o intervalo indicado |
| 500 | Falha inesperada | Reporte com o identificador de rastro |
| 503 | Temporariamente indisponível | Tente de novo após o intervalo indicado |
Distinguindo os 403
Causas diferentes, distinguidas por código:
| Código | Causa | Remédio |
|---|---|---|
PERMISSION_DENIED | Falta um código de permissão. A resposta nomeia qual. | Conceda-o, ou use um papel que o tenha |
ABAC_DENIED | Uma política ABAC negou este registro específico | Revise a política — a permissão existe, o registro está fora do escopo |
SELF_LOCK_FORBIDDEN, SELF_DELETE_FORBIDDEN, SELF_ROLE_REVOKE_FORBIDDEN, SELF_ROLE_ASSIGN_FORBIDDEN | Proteção contra autoação — você não pode desativar, excluir ou remover papéis de si mesmo | Peça a outro administrador |
FORBIDDEN | Outra proteção específica da operação | Leia a mensagem |
A distinção importa porque as correções não têm relação entre si: uma é mudança de papel, outra é mudança de política, e outra normalmente é "peça a outra pessoa".
Por que 404 e não 403 entre organizações
Um registro de outra organização retorna 404, não 403.
Isso não é ofuscação. O isolamento é aplicado no banco de dados, então a linha é genuinamente invisível para a consulta — a plataforma não olhou, encontrou e recusou. Também significa que identificadores não podem ser sondados para descobrir o que existe em outro lugar.
Detalhe de validação
Um 400 carrega uma entrada por campo problemático, cada uma com o campo, um código e uma mensagem. Exiba-as junto aos seus campos em vez de num aviso único — assim quem chama corrige tudo de uma vez.
Erros de regra de negócio
Um 422 significa que a requisição estava bem formada e ainda assim não é permitida, porque uma regra do domínio a proíbe. Eles carregam códigos específicos:
| Código | Levantado quando |
|---|---|
ENTITY_ALREADY_MERGED | Consolidando um registro já consolidado |
ENTITY_STATUS_ENGINE_MANAGED | Definindo situação consolidada diretamente |
CONSENT_NOT_WITHDRAWABLE | Revogando um registro cuja base legal não é consentimento |
WITHDRAW_ALREADY_REVOKED | Revogando um registro já revogado |
UNSUPPORTED_RULE_CONFIG | Salvando uma regra que o motor não consegue honrar |
UNSUPPORTED_VALUE_SHAPE | Gravando um escalar num atributo composto |
INVALID_VALUE_TYPE | Fornecendo um tipo de uso fora da lista vinculada |
NO_ACTIVE_MATCH_PROFILE | Comparando um tipo de entidade sem perfil ativo |
Erros de configuração são deliberadamente levantados ao salvar, não silenciosamente na execução. Uma regra que nunca dispara é pior que nenhuma regra, porque parece cobertura.
Contrapressão
| Código | Situação | Significa |
|---|---|---|
TOO_MANY_ROWS | 400 | A submissão excede o limite de linhas |
PAYLOAD_TOO_LARGE | 413 | O corpo excede o limite de tamanho |
QUEUE_LIMIT_EXCEEDED | 429 | A profundidade de fila da organização foi atingida |
PAYLOAD_QUOTA_EXCEEDED | 429 | A cota de payload foi atingida |
RATE_LIMITED | 429 | Quem chama excedeu seu limite de taxa |
QUEUE_SATURATED | 503 | A plataforma está saturada |
429 e 503 carregam um intervalo de nova tentativa. Respeite-o. Veja limites para os valores.
Identificadores de rastro
Todo erro carrega um. Ele localiza a requisição nos logs diretamente, o que é muito mais rápido que reconstruir a partir de uma descrição.
Exponha-o nas suas próprias interfaces. Um erro que um usuário consegue reportar por identificador é diagnosticável; um descrito de memória normalmente não é.
Todo erro que quem chama consegue causar deveria ser um 4xx com código significativo. Um 500 significa que um caso não tratado chegou à superfície. Reporte com o identificador de rastro em vez de contornar — a correção é mapear o erro.
A seguir
Última verificação no commit d3c2586b (2026-08-03)