Pular para conteúdo

Glossário de Códigos de Erro

Referência oficial dos erros da integração Nayax ↔︎ Saipos, jobs de outbox e camada HTTP/Prisma. Use isto para padronizar tratamento, observabilidade e DX.


Convenções

  • error: título curto e traduzido.
  • message: detalhe legível (pode ser oculto em produção).
  • code: identificador técnico quando existir (ex.: P2002, 901).
  • status: HTTP status code.
  • requestId: correlação nos logs.
  • timestamp: ISO UTC.

Sumário


HTTP genéricos

status error Quando Ação cliente
400 Bad Request Payload inválido, domínio inválido, duplicidade de evento em produção Corrigir e reenviar
401 Unauthorized Sem autenticação Autenticar
403 Forbidden Autenticado mas sem permissão Revisar permissões
404 Not Found Recurso não existe Validar IDs
409 Conflito Violação de unicidade (espelha P2002) Ajustar dados
422 Unprocessable Entity Estrutura válida, regra de negócio não satisfeita Corrigir domínio
500 Erro interno do servidor Exceção não tratada Retry com backoff
503 Service Unavailable (opcional) Dependência externa indisponível Retry com backoff

Handler de fallback: erros sem statusCode viram 500 e ocultam message fora de NODE_ENV=development.


Prisma

code status error Descrição Exemplo prático
P2002 409 Conflito Unique constraint violation (scheduleId,userId,date,shiftId)
P2025 404 Não encontrado Registro alvo não existe para update/delete update() em ID inexistente

Tratamento direto no errorHandler:

  • P2002409 { error: 'Conflito', message: 'Registro duplicado' }
  • P2025404 { error: 'Não encontrado', message: 'Registro não encontrado' }

Autenticação/Parceiro (Saipos)

Alguns erros do parceiro usam códigos próprios no payload:

code status error Significado Ação
901 401 Auth inválida (Saipos) Token/credenciais inválidos ou expirados Invalidar cache e renovar credenciais
902 401 Auth ausente (Saipos) Credenciais não informadas Configurar idPartner/secret

O JobsProcessor invalida tokenCache automaticamente quando detecta 401/901/902.


Aplicação (regras/negócio)

Erros lançados no fluxo de ingestão e regras:

status error Quando Origem
400 Autenticação necessária Requisição sem actor NayaxService.ingestAndEnqueue
400 Você não possui um restaurante cadastrado Usuário autenticado sem vínculo userRestaurant como OWNER NayaxService.ingestAndEnqueue
400 Transação {transactionKey} já foi processada Evento duplicado em produção Idempotência por transactionKey
200 (ignorado deliberadamente) Evento duplicado de teste (STORE1001/isTestTransaction) é ignorado Idempotência relaxada

Jobs de Outbox

Estados e transições administrados pelo JobsProcessor (cron */20 * * * * *):

Estados

status Descrição Disparo/Transição
PENDING Criado, aguardando processamento criação do evento Nayax
PROCESSING Em execução por um worker claim otimista via updateMany
SENT Enviado com sucesso ao parceiro Após createOrder/cancelOrder OK
FAILED Falha temporária; será re-tentado com backoff Erros 5xx, network, timeouts
DLQ Falha permanente; não re-tentará 400/422 domínio inválido no parceiro

Política de Backoff (exponencial com jitter)

Tentativa (n) Base (ms) Janela com jitter (~±20%)
1 30.000 24.000 – 36.000
2 120.000 96.000 – 144.000
3 300.000 240.000 – 360.000
4 900.000 720.000 – 1.080.000
5 1.800.000 1.440.000 – 2.160.000
≥6 3.600.000 2.880.000 – 4.320.000

Reaper: jobs travados em PROCESSING além do TTL (PROCESSING_TTL_MS, default 120.000 ms) são revertidos para FAILED com agendamento do próximo run.


Formato de resposta de erro

HTTP (REST)

{
  "error": "Conflito",
  "message": "Registro duplicado",
  "code": "P2002",
  "status": 409,
  "requestId": "ac76763c9d2e",
  "timestamp": "2025-10-28T10:57:12.931Z"
}

Em desenvolvimento (NODE_ENV=development), mensagens internas podem incluir stack e detalhes adicionais.

Log estruturado do Job (falha)

{
  "id": "job-uuid",
  "attempts": 3,
  "nextStatus": "FAILED",
  "backoff": 300000,
  "status": 502,
  "raw": { "partnerMessage": "gateway timeout" },
  "message": "Network error"
}

Exemplos

1) P2002 (unicidade)

Entrada: criação de agendamento duplicado Saída (HTTP 409):

{
  "error": "Conflito",
  "message": "Registro duplicado",
  "code": "P2002",
  "status": 409
}

2) Duplicidade de transação Nayax (produção)

Saída (HTTP 400):

{
  "error": "Bad Request",
  "message": "Transação 12345 já foi processada",
  "status": 400
}

3) Duplicidade de transação Nayax (teste)

Saída: 200 OK e log "Ignorando duplicata" (idempotência relaxada).

4) Saipos 901/902 (auth)

Saída (HTTP 401):

{
  "error": "Auth inválida (Saipos)",
  "code": 901,
  "status": 401
}

Ação do worker: limpar tokenCache e reautenticar.

5) DLQ por erro 422 do parceiro

Transição: PROCESSINGDLQ Registro no job:

{
  "status": "DLQ",
  "lastError": {
    "msg": "Campo obrigatório ausente: cod_store",
    "status": 422,
    "data": { "error": "Unprocessable Entity" }
  }
}

Matriz de decisões (cliente)

status/parceiro Deve re-tentar? Deve corrigir payload? Observação
400 / 422 Erro de domínio
401 / 901 / 902 ✅ (após auth) ⚠️ Renove credenciais
404 Recurso inexistente
409 Conflito de unicidade
5xx / timeout ✅ (backoff) Falha transitória

Observabilidade

Para correlação eficiente:

  • Logs estruturados contêm requestId, eventKey, job.id, status, action, attempts.
  • Console hard logs no JobsProcessor (pré/envio e erro) garantem visibilidade fora do Logger.
  • Campos recomendados para dashboards: taxa de DLQ, latência, tentativas médias, distribuições de status, top lastError.msg.

Anexos (trechos relevantes)

Filtro de erros no errorHandler

// Prisma
if (err.code === 'P2002') return res.status(409).json({ error: 'Conflito', message: 'Registro duplicado', code: 'P2002' });
if (err.code === 'P2025') return res.status(404).json({ error: 'Não encontrado', message: 'Registro não encontrado', code: 'P2025' });

// Custom
if (err.statusCode) return res.status(err.statusCode).json({ error: err.message });

// Genérico
return res.status(500).json({
  error: 'Erro interno do servidor',
  message: process.env.NODE_ENV === 'development' ? err.message : undefined,
});

Classificação no JobsProcessor (resumo)

  • 400/422DLQ
  • 401/901/902 → limpa token, re-tenta
  • Demais erros → FAILED + backoff exponencial (com jitter)

Takeaway: DLQ para erros de domínio, FAILED para transitórios, idempotência rígida em produção e relaxada em teste. Ajuste, reprocessa, escala.