Padroes de tratamento de erros com Claude Code: classifique falhas na borda
Guia pratico de Claude Code para validacao de API, APIs externas, jobs, TypeScript e caminhos de recuperacao.
Tratamento de erros nao e simplesmente espalhar try-catch pelo codigo. Quando pedimos ao Claude Code apenas para “corrigir este erro”, o patch tende a ficar impreciso: tudo vira 500, os logs nao mostram quem pode agir e falhas de validacao se misturam com indisponibilidade de fornecedor externo.
O padrao mais util e classificar a falha na borda e deixar claro como recuperar. Borda e o ponto em que a aplicacao encontra algo menos controlavel: corpo de uma requisicao API, provedor de pagamento, CRM, servico de email, job agendado, importacao CSV ou tela do usuario. Quando a borda esta clara, Claude Code consegue implementar regras concretas: validacao retorna 400, falha externa temporaria pode ter retry, e batch com erro deixa uma trilha para reexecucao segura.
Este artigo explica a ideia para iniciantes, mas com foco de producao. Voce tera um exemplo TypeScript copiavel, tres casos de uso, armadilhas comuns, prompt de revisao para Claude Code, referencias oficiais e uma chamada para transformar o tema em treinamento ou material reutilizavel.
Comece pela recuperacao
Antes de escolher se o tipo se chama AppError ou DomainError, decida o que o sistema deve fazer depois da falha.
| Borda | Exemplo | Resposta | Recuperacao |
|---|---|---|---|
| Validacao de API | Email invalido, numero fora do intervalo, JSON quebrado | 400 | Usuario corrige a entrada |
| API externa | Pagamento, CRM, email ou analytics indisponivel | 502 ou 503 | Retry, pausa ou erro temporario |
| Job/Batch | Relatorio noturno, importacao CSV, notificacao | Registro interno de falha | Reexecucao segura, fila de erro, alerta |
Um message legivel ajuda, mas nao basta. O programa precisa de campos como kind, code, retryable e status para decidir. Isso tambem ajuda Claude Code a revisar comportamento, em vez de inferir intencao a partir de texto livre.
Exemplo TypeScript executavel
O exemplo abaixo roda em Node.js 18 ou superior. Ele usa tsx para executar TypeScript diretamente e nao chama uma API real. O fetcher e injetado para que a falha seja reproduzivel.
npm install -D tsx typescript
npx tsx error-patterns-demo.ts
type Kind = "validation" | "external" | "job";
type AppError = { kind: Kind; code: string; message: string; retryable: boolean; status: number; detail?: unknown };
type Result<T> = { ok: true; value: T } | { ok: false; error: AppError };
const ok = <T>(value: T): Result<T> => ({ ok: true, value });
const fail = <T>(error: AppError): Result<T> => ({ ok: false, error });
function parseUser(body: unknown): Result<{ email: string; age: number }> {
if (typeof body !== "object" || body === null) {
return fail({ kind: "validation", code: "BODY_REQUIRED", message: "body must be an object", retryable: false, status: 400 });
}
const data = body as Record<string, unknown>;
if (typeof data.email !== "string" || !data.email.includes("@")) {
return fail({ kind: "validation", code: "EMAIL_INVALID", message: "email is invalid", retryable: false, status: 400 });
}
if (typeof data.age !== "number" || data.age < 13) {
return fail({ kind: "validation", code: "AGE_INVALID", message: "age must be 13 or greater", retryable: false, status: 400 });
}
return ok({ email: data.email, age: data.age });
}
async function callPartner(fetcher: () => Promise<Response>): Promise<Result<{ id: string }>> {
try {
const response = await fetcher();
if (!response.ok) {
return fail({ kind: "external", code: "PARTNER_HTTP", message: `partner returned ${response.status}`, retryable: response.status >= 500, status: 503 });
}
const json = (await response.json()) as { id?: unknown };
if (typeof json.id !== "string") {
return fail({ kind: "external", code: "PARTNER_PAYLOAD", message: "partner payload is invalid", retryable: false, status: 502, detail: json });
}
return ok({ id: json.id });
} catch (error) {
return fail({ kind: "external", code: "PARTNER_UNREACHABLE", message: "partner is unreachable", retryable: true, status: 503, detail: error });
}
}
async function runJob<T>(name: string, work: () => Promise<T>, retries = 2): Promise<Result<T>> {
for (let attempt = 1; attempt <= retries + 1; attempt += 1) {
try {
return ok(await work());
} catch (error) {
if (attempt <= retries) continue;
return fail({ kind: "job", code: "JOB_FAILED", message: `${name} failed`, retryable: true, status: 500, detail: { attempt, error } });
}
}
return fail({ kind: "job", code: "JOB_FAILED", message: `${name} failed`, retryable: true, status: 500 });
}
console.log(parseUser({ email: "bad", age: 10 }));
console.log(await callPartner(async () => new Response("down", { status: 503 })));
console.log(await runJob("daily-report", async () => ({ exportedRows: 42 })));
Caso 1: validacao de entrada API
Erro de validacao geralmente pode ser corrigido pelo usuario. Email invalido, idade baixa demais, JSON fora do formato ou plano inexistente nao devem parecer queda do servidor. No exemplo, parseUser classifica a falha como validation, retorna 400 e define retryable: false.
Isso torna o sistema mais claro. O frontend pode apontar o campo errado, o backend pode filtrar logs por EMAIL_INVALID, e Claude Code pode criar testes de falha, nao apenas de sucesso. Para evoluir essa parte, leia tambem testes de API com Claude Code e estrategias de teste com Claude Code.
Caso 2: falha de API externa
Servicos externos falham mesmo quando seu codigo esta certo. Pagamentos, emails, CRM, planilhas e analytics podem retornar timeout, rate limit ou payload inesperado. O ponto central e separar o que pode ser tentado novamente do que precisa de correcao.
No exemplo, 5xx vira retryable: true, enquanto payload com formato errado vira retryable: false. Repetir uma resposta impossivel so cria ruido em filas e logs. Para confirmar a semantica de response.ok, veja MDN Response.ok. Em APIs Express, consulte tambem Express error handling.
Caso 3: falha de job ou batch
Jobs falham longe da tela do usuario. Relatorio noturno, importacao CSV, emissao de fatura e envio de notificacoes precisam deixar pistas para reexecucao. runJob guarda nome do job, tentativa final e se o erro e reexecutavel. Em producao, isso deve ir para logs estruturados, fila de falha, tela administrativa ou alerta.
A pergunta decisiva e: repetir e seguro? Se uma importacao CSV cria linhas duplicadas, ou se um job de cobranca cobra duas vezes, retry aumenta o problema. Peca para Claude Code revisar idempotencia, efeitos colaterais e testes de replay, nao apenas compilar o codigo.
Armadilhas comuns
A primeira armadilha e catch { return null; }, que apaga a evidencia. A segunda e expor stack trace, SQL, variaveis de ambiente ou partes de tokens para o usuario. Para esse lado, veja auditoria de seguranca com Claude Code. A terceira e tentar tudo novamente. Erros de validacao e payloads invalidos nao melhoram com o tempo.
Tambem e comum criar tipos bons sem registrar a regra do time. TypeScript ajuda com narrowing e unioes discriminadas, mas alguem pode voltar a throw new Error("failed"). Use a referencia oficial de TypeScript Narrowing e documente a regra em AGENTS.md ou CLAUDE.md.
Prompt de revisao para Claude Code
Revise o tratamento de erros deste PR.
Verifique:
1. Falhas sao classificadas nas bordas API, API externa e job/batch.
2. Erros corrigiveis pelo usuario nao viram 500.
3. retryable e non-retryable estao separados.
4. A resposta nao expoe stack trace, SQL, segredos ou caminhos internos.
5. Logs incluem code, kind, attempt e cause seguro.
6. Existem pelo menos 3 testes de caminhos de falha.
Retorne o menor patch seguro e os testes correspondentes.
Para travar esses caminhos, o Node.js test runner costuma ser suficiente. Configuracoes e memoria de projeto do Claude Code podem ser verificadas em Claude Code overview. Para trabalhar com testes antes da correcao, siga para TDD com Claude Code e tecnicas de debugging.
CTA e resultado testado por Masa
Tratamento de erros e excelente para treinamento, porque junta API, logs, seguranca, testes e operacao. Para comecar, baixe a folha gratuita. Se precisar de prompts, checklists e templates prontos para equipe, veja a biblioteca de produtos. Para adaptar um repositorio existente, a pagina de treinamento e consultoria Claude Code ajuda a mapear APIs, integracoes externas e batches.
No fluxo de Masa, colocar validacao, APIs externas e batches em uma forma parecida com AppError encurtou os prompts. Antes era “corrija este erro”; agora e “validation retorna 400, external usa retryable, job preserva attempt”. A revisao fica concentrada em resposta, log e teste. Nao e arquitetura magica, mas e muito mais operavel do que varios 500 anonimos.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Permission receipt no Claude Code: escopo, prova e rollback
Padrão de permission receipt para Claude Code: ações permitidas, limites de aprovação, comandos de prova, rollback e CTA de receita.
Agent Harness seguro para Claude Code e Codex: permissoes, verificacao e rollback
Monte uma base segura para agentes com Claude Code e Codex usando politicas, plano, verificacao e recuperacao.
Subagentes no Claude Code: guia prático para delegar trabalho com segurança
Guia prático de subagentes no Claude Code para dividir artigos e código: regras, prompts, riscos e checklist.