Claude Code inventou um método que não existe? Como identificar e corrigir a alucinação antes de commitar

Claude Code alucinação: código com método inventado antes do commit
Resposta rápida

Alucinação do Claude Code é quando o agente entrega um código bonito que chama método, parâmetro ou pacote inexistente. Os sinais são sempre os mesmos: nome que descreve exatamente o que você pediu, assinatura plausível demais e explicação confiante sem nenhuma fonte. Para confirmar, procure o símbolo no código realmente instalado com Read, Grep e Glob, inspecione a dependência com Bash e cheque a doc oficial com WebSearch e WebFetch. Se não aparece em nenhuma dessas camadas, ele não existe. Para prevenir: plan mode, regra escrita no CLAUDE.md e um type check no hook PostToolUse

Fala aí, beleza? O diff tá lindo

Indentação certa, nome de variável coerente, o padrão do teu projeto respeitado linha por linha

Aí você lê com calma e percebe: o método que ele chama simplesmente não existe naquela biblioteca

Isso não é bug raro e não é culpa sua por ter escrito um prompt ruim

É um comportamento previsível de modelo de linguagem: quando falta informação, ele prefere completar a lacuna a admitir que não sabe

E o custo disso quase nunca aparece na hora, aparece depois do commit, no CI vermelho ou no colega perguntando de onde saiu aquela função 😀

Os sinais que denunciam um método inventado no código gerado

O sintoma: o código bom demais pra ser verdade

Método inventado tem cara. Se liga nos marcadores:

  • O nome descreve exatamente o que você pediu. Você pediu "validar o payload antes de enviar" e apareceu um client.validatePayloadBeforeSend(). Convenientão demais
  • A assinatura é plausível demais. Os parâmetros resolvem o teu caso específico, na ordem que você queria, com o default que você precisava
  • Falta o import, a rota ou o require real. O símbolo é usado, mas não veio de lugar nenhum, ou veio de um caminho que ninguém consegue apontar
  • A explicação é confiante e sem referência. Ele te conta o que o método faz internamente, mas não cita versão, doc nem arquivo
  • O parâmetro mágico. A função existe, beleza, mas aquele argumento específico (strict: true, retry, timeout) foi enxertado

Esse último é o mais traiçoeiro. O símbolo existe, então o teu olho passa batido, e o que quebra é a chamada

Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 45min

Por que o modelo faz isso:

Porque completar padrão é literalmente o trabalho dele

A biblioteca que você usa tem um formato de API, o modelo aprendeu esse formato, e quando o pedaço exato não está na memória dele, o padrão preenche o buraco

É como um dev que decorou o estilo do framework, mas não abriu a doc da versão que você instalou: ele vai escrever algo que PARECE daquele framework

E isso é mensurável. O caso mais estudado é o da alucinação de pacote, quando o modelo gera código que referencia um pacote que não existe (um pip install xyz ou npm install xyz com um xyz fictício)

O trabalho que deu nome e escala ao problema foi apresentado no USENIX Security 2025: o paper We Have a Package for You! A Comprehensive Analysis of Package Hallucinations by Code Generating LLMs, no 34th USENIX Security Symposium

Estudo Escopo Taxa de pacote alucinado
USENIX Security 2025 576.000 amostras de código, 16 LLMs, duas linguagens e dois conjuntos de prompts pelo menos 5,2% em modelos comerciais e 21,7% em open source
Preprint de 2026, de Aleksandr Churilov 5 modelos de fronteira, 199.845 prompts pareados de Python e JavaScript entre 4,62% e 6,10% no geral

O estudo de 2025 catalogou 205.474 nomes únicos de pacotes alucinados. Duzentos e cinco mil nomes que não existem 😛

Já o preprint de 2026, de autoria do pesquisador independente Aleksandr Churilov, reavaliou cinco modelos de fronteira lançados entre outubro de 2025 e março de 2026 (Claude Sonnet 4.6, Claude Haiku 4.5, GPT-5.4-mini, Gemini 2.5 Pro e DeepSeek V3.2), validando os nomes contra o PyPI e o npm

A taxa geral ficou entre 4,62% (Claude Haiku 4.5) e 6,10% (GPT-5.4-mini)

Ou seja: caiu bastante em relação a 2025, mas NÃO zerou

Um detalhe honesto antes que alguém use isso errado: esses números medem nome de pacote, não método nem parâmetro de API. Não existe, nas fontes que eu uso aqui, um percentual de "método inventado". O que esses estudos mostram é a mecânica do problema, e a mecânica é a mesma

Como resolver: leitura ativa do diff

A solução aqui não é ferramenta, é hábito

Antes de rodar qualquer coisa, passa o olho no diff procurando API nova. Qualquer símbolo de biblioteca externa que não estava no teu código ontem entra na lista de suspeitos

Rodar e esperar o erro parece mais rápido, mas só funciona pro código que executa naquele caminho. Método inventado dentro de um if que quase nunca cai é bug de produção esperando a vez

Revisar por API nova ANTES de rodar, não depois

Como confirmar contra a fonte real antes de aceitar a mudança

O sintoma: você desconfia, mas não sabe onde olhar

A suspeita bateu, você não tem certeza, e o caminho de menor esforço é rodar e ver no que dá

A causa disso é simples e meio desconfortável: a gente trata o output do agente como se fosse documentação

Não é. É uma proposta. E proposta se confere

A verificação em três camadas:

O próprio Claude Code já tem as ferramentas pra isso. Read, Grep, Glob, Bash, WebSearch e WebFetch estão entre as ferramentas documentadas dele

  1. Camada 1: o código que está instalado de verdade no teu projeto. Peça pro Claude procurar o símbolo com Grep e Glob dentro da dependência real, não na memória dele
Use Grep e Glob para procurar a definição de validatePayloadBeforeSend
dentro da pasta da dependência instalada neste projeto.
Mostre o arquivo e a linha exata onde ela é declarada.
Se não encontrar, diga que não encontrou.

O erro comum deste passo: aceitar "encontrei algo parecido". Parecido não serve. Ou o símbolo está declarado com aquele nome exato, ou não está. E se ele te responder que o arquivo não existe quando você sabe que existe, aí o problema é outro, vale conferir os motivos do Claude Code não achar o arquivo antes de concluir qualquer coisa

  1. Camada 2: a dependência e a versão. Com o Bash, dá pra inspecionar o que está instalado e qual versão é. Isso importa porque método que existe na major nova não existe na que você travou no lockfile

O erro comum deste passo: conferir a doc da versão mais recente enquanto o projeto roda uma anterior. A doc está certa, o teu projeto é que é outro

  1. Camada 3: a documentação oficial. WebSearch pra achar, e WebFetch pra extrair. O WebFetch recebe uma URL e um prompt do que extrair da página, então dá pra ser bem específico
Use WebFetch nesta URL da documentação oficial e extraia LITERALMENTE
a assinatura do método e a lista de parâmetros aceitos.
Se o método não aparecer na página, responda exatamente: NÃO ENCONTRADO.

O erro comum deste passo: mandar ele "confirmar se o método existe". Pergunta fechada assim convida o modelo a concordar com você. Peça o trecho literal, não o veredito

Regra de ouro: se o símbolo não aparece em nenhuma das três camadas, ele não existe. Ponto

Como prevenir: peça a verificação no mesmo turno

O jeito mais barato de não fazer isso tudo é não precisar fazer

Em vez de pedir o código e depois auditar, peça as duas coisas juntas: escreva a mudança e, no mesmo turno, mostre onde cada símbolo externo está declarado

Custa uns segundos a mais e te poupa o ciclo inteiro de suspeitar, checar e refazer

E pra não ter que repetir esse pedido em toda sessão, essa exigência vira regra escrita no CLAUDE.md do projeto, que é o que eu mostro mais pra frente no post

Quando o inventado é o pacote inteiro: o risco de instalar o que não existe

O sintoma: um install que parece legítimo

O agente sugere um pip install ou um npm install, o nome do pacote faz todo sentido pro que você pediu, e a mão já vai no enter

Aqui a causa tem nome: alucinação de pacote, exatamente o fenômeno analisado no estudo do USENIX Security 2025 lá de cima

E o preprint de 2026 trouxe uma agravante que vale parar pra ler

Os nomes que os modelos inventam em comum:

Os cinco modelos de fronteira testados inventaram nomes de pacote idênticos entre si: 127 nomes apareceram em comum

Depois de revisão da PyPI Security e da Socket, 53 desses nomes (41 no PyPI e 12 no npm) ainda estavam livres para registro em abril de 2026

Sacou o problema? Se modelos diferentes convergem no mesmo nome fictício, esse nome vira um alvo previsível. É o que se chama de slopsquatting

Sendo justo com o que a fonte diz: o trabalho identifica alvos POTENCIAIS e não traz evidência de que esses 53 nomes tenham sido registrados maliciosamente. A Socket e a PyPI Security atuaram na revisão e na divulgação, a autoria do preprint é do Churilov

Mas "ninguém registrou ainda" não é garantia de nada, é só uma foto de abril de 2026

Como resolver e prevenir:

Confira o nome no registro oficial antes de instalar. Se o pacote não está lá, acabou a conversa

E a regra que eu acho que todo mundo deveria ter tatuada: install é sempre decisão humana

Deixar o agente rodar instalação sozinho é entregar pra ele a única etapa em que o erro dele executa código de terceiro na tua máquina. Não vale a economia de dois segundos

Tome cuidado também pra não confundir esse tipo de falha com problema de ambiente: se o que quebra é o próprio setup, é outro papo, e aí o caminho é olhar os erros comuns de instalação do Claude Code

Como reescrever o prompt para o agente parar de preencher lacuna com chute

O sintoma: confiança total sobre biblioteca não consultada

Você pergunta, ele responde na hora, com segurança, sobre uma lib que ele não abriu em nenhum momento da sessão

A causa não é o modelo ser mentiroso. É que o teu prompt não deu saída honesta nem exigiu fonte

Se a única resposta aceitável é o código, ele entrega código. Mesmo quando a resposta certa seria "não sei qual é a assinatura dessa função"

As três técnicas da doc, traduzidas pro teu dia:

A página Reduce hallucinations da documentação da plataforma Claude lista três técnicas: permitir explicitamente que o Claude diga "não sei", pedir verificação com citações e pedir que ele extraia trechos literais da fonte antes de responder

No contexto de código, isso vira frase pronta:

1) SAÍDA HONESTA
Se você não tiver certeza de que este método existe nesta versão da
biblioteca, responda "não sei" e pare. Não proponha alternativa inventada.

2) CITAÇÃO
Para cada símbolo externo que você usar, cite o arquivo e a linha onde
ele está declarado, ou a URL da doc oficial. Sem citação, não use.

3) TRECHO LITERAL PRIMEIRO
Antes de escrever qualquer código, cole os trechos literais da doc ou
do fonte que comprovam a assinatura que você vai chamar.
Só depois escreva o diff.

A terceira é a que mais muda o jogo, porque inverte a ordem

O modelo que escreve código primeiro e justifica depois vai justificar o que ele escreveu. O modelo que cola o trecho primeiro fica preso ao que a fonte diz

O reforço: plan mode antes do diff

O Claude Code tem um modo de planejamento em que ele pesquisa e propõe mudanças sem escrever arquivos até o plano ser aprovado

Você entra nele com Shift+Tab, que cicla os modos de permissão, ou já abrindo a sessão assim:

claude --permission-mode plan

O ganho aqui é de ordem de leitura: você vê a API que ele PRETENDE chamar enquanto ainda é texto num plano, não depois que virou diff em cinco arquivos

É muito mais fácil dizer "esse método aí não existe, confere" antes de ter código pra desfazer 🙂

Como travar a regra para não repetir a correção toda sessão

O sintoma: você corrige hoje, volta amanhã

Você explica, ele entende, corrige, agradece

Sessão nova, mesma invenção

A causa é boba e universal: a regra ficou no chat. Chat é volátil, projeto é permanente

Escreva a política na memória do projeto:

O Claude Code tem memória em arquivos CLAUDE.md hierárquicos: ./CLAUDE.md guarda a memória do projeto e ~/.claude/CLAUDE.md a memória do usuário, e os dois são editáveis pelo comando /memory

O que entra lá é uma política curta, não um manifesto:

## Verificação de API

- Nunca chame método, parâmetro ou endpoint sem antes localizar a
  declaração no código instalado ou na doc oficial
- Cite arquivo e linha (ou URL) para cada símbolo externo novo
- Se não encontrar a declaração, diga que não encontrou e pare
- Nunca rode instalação de pacote sozinho: sugira e espere aprovação

É essa política que faz o agente entregar código e prova no mesmo turno, sem você ter que pedir de novo a cada sessão

Projeto que usa lib interna ganha mais ainda com isso, porque é justamente onde o modelo tem menos material e mais tendência a chutar o formato

Apoie em hooks: a barreira que não depende do teu olho

Hooks do Claude Code são comandos de shell definidos por você que rodam em eventos do ciclo de vida, configurados na chave hooks do settings.json: .claude/settings.json na raiz do projeto para hooks de projeto, ~/.claude/settings.json para hooks globais

O encaixe mais natural pro nosso problema é o evento PostToolUse, que dispara depois que a ferramenta roda com sucesso e serve pra formatação, testes e notificações. Com o matcher Write|Edit ele roda só em modificação de arquivo:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npm run typecheck"
          }
        ]
      }
    ]
  }
}

Troque o npm run typecheck pelo comando de type check ou de teste do teu projeto

E o porquê disso funcionar é bem direto: símbolo inexistente estoura no type check. Não é heurística, é o compilador dizendo que aquilo não está declarado em lugar nenhum

Tem também o PreToolUse, que age antes. Nele, sair com exit code 2 bloqueia a chamada da ferramenta e devolve o conteúdo do stderr ao modelo como motivo do bloqueio (o exit code 1 é só aviso, não bloqueia)

Caveat honesto antes que você monte teu fluxo inteiro em cima disso: existe a issue #24327 no repositório oficial do Claude Code relatando que, ao ser bloqueado por um PreToolUse com exit 2, o Claude às vezes para e devolve o controle ao usuário em vez de agir sobre o feedback do stderr. O comportamento é intermitente

Não tenho fonte dizendo que foi corrigido, então trate o bloqueio como freio, não como instrução garantida

Nota operacional sobre o /hooks:

O comando /hooks abre um navegador de hooks que mostra os eventos e os hooks configurados (evento, matcher, tipo, arquivo de origem e comando)

Mas esse menu é somente leitura

Pra adicionar ou remover hook, você edita o settings.json na mão. Já vi gente ficar procurando o botão de "novo hook" ali dentro, não tem 😀

A ideia geral: a barreira automática pega o que a leitura humana deixa passar, principalmente na sexta-feira às 18h

Conclusão

O agente não te engana por má fé

Ele erra por ser bom demais em parecer certo, e esse é exatamente o tipo de erro que passa pela revisão rápida

Por isso a defesa não é desconfiança genérica (desconfiar de tudo cansa e você para em duas semanas), é processo: marcador de sintoma no diff, verificação em camadas, install como decisão humana, prompt com saída honesta e regra escrita no lugar certo

Próximo passo concreto pra hoje, e é rapidinho: abre o ./CLAUDE.md do teu projeto e escreve a política de verificação de API

Depois coloca um type check no PostToolUse com matcher Write|Edit

Só isso já muda a taxa de invenção que chega no teu commit

Deu certo aí? Quebrou em algum ponto? Me conta, que rende continuação…

Até o próximo post! =)

Perguntas frequentes

Claude Code pode inventar um método que não existe na biblioteca que eu uso?

Sim, é um comportamento previsível de modelo de linguagem: quando falta informação sobre a API real, ele completa a lacuna com o padrão que aprendeu em vez de admitir que não sabe. O caso mais estudado e mensurado é o de pacote inventado (um pip install ou npm install com nome fictício), mas a mesma mecânica de completar padrão vale pra método e parâmetro de API, mesmo sem um percentual específico medido pra isso.

Como faço o Claude Code confirmar se um método existe antes de eu aceitar a mudança?

Peça pra ele usar Grep e Glob pra procurar a definição exata dentro da pasta da dependência instalada no seu projeto, mostrando o arquivo e a linha onde ela está declarada. Se não encontrar, a instrução é dizer que não encontrou, em vez de aceitar algo ‘parecido’ como confirmação.

Existe alguma forma de bloquear automaticamente código com método inventado no Claude Code?

O caminho mais direto é um hook PostToolUse com matcher Write|Edit rodando o type check ou os testes do projeto, porque símbolo inexistente estoura na checagem de tipos. Também existe o evento PreToolUse, que age antes da ferramenta rodar, mas trate ele como freio e não como instrução garantida: há relato de comportamento intermitente na issue #24327 do repositório oficial. Nos dois casos, hooks são configurados na chave hooks do settings.json, do projeto ou do usuário.

Alucinação de pacote é a mesma coisa que alucinação de método ou parâmetro de API?

Não exatamente. Alucinação de pacote é o problema mais estudado e mensurado, com o USENIX Security 2025 (576.000 amostras, 16 LLMs) e o preprint de 2026 de Aleksandr Churilov (199.845 prompts pareados) medindo taxas de nomes de pacote validados contra PyPI e npm. Não existe, nas fontes usadas aqui, um percentual equivalente pra método inventado, mas a mecânica de completar padrão quando falta informação é a mesma.

Dá pra fazer o Claude Code avisar quando não tem certeza em vez de inventar uma resposta?

Dá, e é o que a página Reduce hallucinations da documentação da plataforma Claude sugere: permitir explicitamente que o Claude diga ‘não sei’, pedir verificação com citações e pedir que ele extraia trechos literais da fonte antes de responder. No dia a dia, isso vira regra fixa no CLAUDE.md do projeto (nunca usar símbolo externo sem citar arquivo e linha ou URL, e parar quando não encontrar a declaração), reforçada pela revisão do plano no modo de planejamento antes de qualquer arquivo ser escrito.

Por que a taxa de alucinação de pacote caiu em 2026 mas não chegou a zero?

O preprint de 2026 mediu entre 4,62% (Claude Haiku 4.5) e 6,10% (GPT-5.4-mini) nos cinco modelos de fronteira avaliados, contra pelo menos 5,2% em comerciais no estudo de 2025. A queda existe, mas os cinco modelos ainda inventaram 127 nomes de pacote em comum, e 53 deles (41 no PyPI e 12 no npm) seguiam livres pra registro em abril de 2026, segundo a revisão da Socket e da PyPI Security.



Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares