npm ERR! ERESOLVE: como corrigir conflitos de peerDependencies sem quebrar o projeto
Publicado em 2026-08-29T20:13:00Z · atualizado em 2026-08-29T19:13:14+00:00
O erro **npm ERR! ERESOLVE unable to resolve dependency tree** aparece quando o npm não consegue construir uma árvore de dependências que satisfaça, ao mesmo tempo, as versões exigidas pelo projeto e pelos pacotes instalados. Apagar `node_m
npm ERR! ERESOLVE: como corrigir conflitos de peerDependencies sem quebrar o projeto
O erro npm ERR! ERESOLVE unable to resolve dependency tree aparece quando o npm não consegue construir uma árvore de dependências que satisfaça, ao mesmo tempo, as versões exigidas pelo projeto e pelos pacotes instalados. Apagar node_modules pode limpar resíduos, mas não torna duas faixas incompatíveis. Usar --force pode concluir a instalação, porém transfere a inconsistência para a execução, para os testes ou para o ambiente de produção.
Este guia mostra como ler a mensagem, encontrar quem exige cada versão, distinguir dependencies de peerDependencies, usar npm explain e corrigir a raiz do conflito. O laboratório é pequeno e reproduzível; depois dele, você poderá aplicar o mesmo raciocínio em React, ESLint, Vite, plugins, bibliotecas de componentes e outras pilhas Node.js.
Legenda: ERESOLVE surge quando não existe uma versão única capaz de satisfazer todas as relações obrigatórias da árvore.
Leia o conflito como uma equação de versões
Considere o trecho:
Found: react@18.3.1
node_modules/react
react@"^18.3.1" from the root project
Could not resolve dependency:
peer react@"^17.0.0" from plugin-antigo@2.0.0
O projeto pede React compatível com ^18.3.1; o plugin declara que precisa encontrar React ^17.0.0 no consumidor. Não há interseção. O npm não está dizendo apenas “algo deu errado”: ele informa as duas restrições incompatíveis e o pacote que introduziu a segunda.
Comece anotando quatro dados: pacote em conflito, versão encontrada, faixa solicitada e dependência que fez a solicitação. Essa leitura evita a sequência aleatória de apagar pastas, trocar versão do Node e repetir o comando.
dependencies, devDependencies e peerDependencies
Uma entrada em dependencies diz que o pacote precisa daquela biblioteca para funcionar e normalmente permite que o gerenciador instale uma cópia aninhada. devDependencies reúne ferramentas necessárias durante desenvolvimento, teste ou construção. Já peerDependencies declara compatibilidade com uma biblioteca que deve existir no projeto consumidor.
Plugins usam peers porque precisam operar sobre a mesma instância do hospedeiro. Um plugin do ESLint deve conversar com o ESLint do projeto; uma extensão de framework deve corresponder à versão do framework. Duas cópias escondidas nem sempre resolvem, pois podem representar APIs ou contextos diferentes.
A documentação de package.json recomenda faixas de peer tão amplas quanto a compatibilidade real. Fixar um patch específico sem necessidade aumenta conflitos para os consumidores.
Monte um laboratório sem afetar seu projeto
Você pode observar a resolução com pacotes locais. Crie a estrutura:
laboratorio-eresolve/
├── app/
├── host-v1/
├── host-v2/
└── plugin/
Em host-v1/package.json:
{
"name": "host-demo",
"version": "1.0.0",
"main": "index.js"
}
Em host-v2/package.json, use o mesmo nome e versão 2.0.0. Em plugin/package.json:
{
"name": "plugin-demo",
"version": "1.0.0",
"peerDependencies": {
"host-demo": "^1.0.0"
}
}
No app/package.json:
{
"name": "app-demo",
"private": true,
"dependencies": {
"host-demo": "file:../host-v2",
"plugin-demo": "file:../plugin"
}
}
Entre em app e rode npm install. O hospedeiro local está em 2.0.0, enquanto o plugin aceita somente 1.x. Dependendo da versão do npm e do tratamento de pacotes locais, a saída mostrará conflito ou aviso; a equação permanece deliberadamente incompatível. Para corrigir o laboratório, aponte o host para file:../host-v1 ou altere a faixa do plugin somente se você controlar o código e tiver validado a compatibilidade com 2.x.
Descubra quem trouxe o pacote
Não edite o primeiro número que aparece. Use comandos de inspeção:
npm explain nome-do-pacote
npm ls nome-do-pacote --all
npm view nome-do-plugin peerDependencies
npm view nome-do-plugin versions --json
npm explain mostra a cadeia que levou um pacote à árvore. npm ls revela versões instaladas e marca relações inválidas. npm view consulta os metadados publicados, permitindo conferir se uma versão mais recente do plugin ampliou a compatibilidade.
Em relatórios e chamados, guarde as versões de Node e npm:
node --version
npm --version
npm config get registry
Não publique a saída completa sem revisão. URLs privadas de registro, nomes internos e caminhos do usuário podem aparecer nos logs.
Entenda as faixas semver antes de alterar
O operador ^ normalmente permite mudanças que não alteram o primeiro componente diferente de zero. Assim, ^2.3.0 aceita versões a partir de 2.3.0 e abaixo de 3.0.0. O operador ~2.3.0 costuma aceitar correções 2.3.x, mas não 2.4.0. Uma faixa >=2 <4 é mais ampla e só deve ser declarada se o pacote realmente funciona nesse intervalo.
Versões 0.x exigem atenção: antes de 1.0.0, mudanças menores podem quebrar compatibilidade e o comportamento do circunflexo é mais restrito. Pré-lançamentos como 3.0.0-beta.2 não entram automaticamente em qualquer faixa estável.
O objetivo não é “fazer os números caberem” no JSON. É escolher versões cuja API foi testada em conjunto. Leia o guia de migração e as notas de lançamento dos pacotes envolvidos.
Ordem segura de correção
Primeiro, procure uma versão do plugin compatível com o hospedeiro atual:
npm view plugin-exemplo@latest peerDependencies
npm install plugin-exemplo@latest
Se não houver, avalie atualizar ou reduzir o hospedeiro conforme os requisitos do projeto. Uma biblioteca nova pode exigir Node mais recente; um plugin abandonado pode impedir a evolução. Em aplicações grandes, atualize um conjunto coerente por vez e execute testes após cada etapa.
Quando você mantém o plugin, amplie a faixa de peerDependencies apenas depois de testar todas as versões declaradas. Adicione uma matriz de CI para as versões mínimas e máximas suportadas. Uma declaração ampla sem teste apenas empurra o erro da instalação para o usuário.
Legenda: a correção preserva uma combinação suportada; flags de força ficam fora do caminho principal.
package-lock.json não é lixo descartável
O package-lock.json registra a árvore exata gerada e deve ser versionado em aplicações. Ele torna instalações repetíveis, acelera a resolução e documenta mudanças transitivas. Excluir o lockfile e instalar novamente autoriza o npm a escolher versões diferentes dentro das faixas; às vezes o conflito some, mas você mudou muitas variáveis de uma vez.
Antes de regenerar, confirme por que o lock está inconsistente. Se package.json foi alterado intencionalmente, rode npm install e revise o diff do lock. Em integração contínua, prefira npm ci: ele exige lockfile compatível, remove a árvore existente e não reescreve o lock para acomodar diferenças.
git diff -- package.json package-lock.json
npm ci
npm test
Não copie um lockfile de outro projeto. O arquivo descreve aquela árvore e seu pacote raiz.
Quando limpar node_modules ajuda
Uma pasta node_modules antiga pode conter restos de instalações interrompidas ou mudanças de branch. Limpar é válido depois de confirmar que package.json e package-lock.json representam a combinação desejada:
npm ci
O próprio npm ci remove node_modules antes de instalar. Se ele falha porque o manifesto e o lock não correspondem, não esconda o problema: volte à branch correta ou atualize o lock conscientemente com npm install.
Evite comandos destrutivos copiados sem entender, especialmente os que removem arquivos fora do projeto. Confirme o diretório atual com pwd ou Get-Location e mantenha o repositório versionado.
--legacy-peer-deps e --force: o que realmente fazem
--legacy-peer-deps manda o npm ignorar peerDependencies ao construir a árvore, comportamento semelhante ao de versões antigas. --force remove várias proteções. Ambos podem permitir instalação, mas não comprovam que o plugin funciona com o hospedeiro encontrado.
npm install --legacy-peer-deps
npm install --force
Essas flags servem, no máximo, como experimento temporário para confirmar uma hipótese ou manter um ambiente legado enquanto existe plano de correção. Registre a exceção, execute testes de integração e não transforme a flag em resposta automática do README.
Se o projeto só instala com --legacy-peer-deps, a dívida continua presente. Uma atualização futura pode expor falhas de API, múltiplas instâncias ou comportamento incorreto em tempo de execução.
overrides: solução cirúrgica, não adivinhação
O campo overrides do npm permite substituir versões em dependências transitivas. Ele é útil quando uma correção compatível existe, mas uma dependência ainda aponta para faixa antiga. Exemplo:
{
"overrides": {
"biblioteca-transitiva": "4.2.3"
}
}
Antes de usar, leia o changelog, confirme a API e rode testes. Forçar uma versão principal diferente pode quebrar o pacote pai. Comente a decisão no histórico do projeto e crie uma tarefa para remover o override quando a origem atualizar sua dependência.
overrides não deve alterar arbitrariamente a peer incompatível do plugin. Se o plugin declara que não suporta a versão instalada, trate essa informação como um contrato até que testes e manutenção comprovem o contrário.
Teste a árvore corrigida como o ambiente de produção
Após alinhar versões, comece de uma instalação limpa:
npm ci
npm ls --all
npm test
npm run build
Execute também o caminho de inicialização e os testes que usam a integração em conflito. Um plugin de build pode instalar corretamente e falhar apenas ao processar um arquivo específico. Registre versão do Node em .nvmrc, .node-version ou engines, conforme o fluxo da equipe.
Se o projeto usa contêiner, teste a partir de uma imagem sem cache. Se usa CI, reproduza as flags do pipeline. Diferenças entre npm install local e npm ci remoto são uma fonte comum de “funciona na minha máquina”.
Para desenhar a cadeia projeto → plugin → peer e documentar a decisão, use o criador de fluxogramas. A biblioteca de Python e a biblioteca de SQL também ajudam a organizar automações e inventários técnicos ao redor do projeto.
Monorepos e workspaces: descubra qual pacote é o consumidor
Em um monorepo, o manifesto da raiz pode não ser o único responsável. Um workspace declara o plugin, outro declara o hospedeiro e o npm tenta montar uma árvore coerente para o conjunto. Execute a inspeção no diretório raiz e filtre pelo workspace quando necessário:
npm explain pacote-exemplo --workspace app-web
npm ls pacote-exemplo --all --workspaces
npm install plugin-exemplo@3 --workspace app-web
Confira o nome do workspace em package.json; caminhos e suporte a flags dependem da versão do npm. Não resolva um conflito adicionando a dependência à raiz apenas para que ela fique visível por hoisting. Isso cria uma dependência implícita: o pacote consumidor funciona por acaso enquanto a organização da árvore permanece igual.
Cada workspace deve declarar diretamente o que importa em tempo de execução ou desenvolvimento. Se vários pacotes precisam da mesma versão, alinhe as faixas conscientemente e mantenha testes por pacote. Uma biblioteca interna que oferece plugin deve declarar o hospedeiro em peerDependencies e, para seus próprios testes, também em devDependencies.
Verifique ainda se há mais de um lockfile no repositório. Misturar instalação na raiz com npm install dentro de subpastas pode criar árvores independentes e resultados difíceis de reproduzir. Defina um único fluxo para o monorepo, documente a versão do npm e rode o mesmo comando no CI.
Quando o conflito aparece apenas em um workspace, não atualize todos os pacotes automaticamente. Isole a cadeia com npm explain, corrija o consumidor e execute sua suíte antes de expandir a mudança. Esse recorte reduz o risco e produz um diff de lockfile mais compreensível.
Caso prático: framework novo e plugin abandonado
Suponha que a aplicação precisa atualizar framework-x de 4 para 5 por requisito de segurança, mas plugin-y declara peer ^4. Há quatro caminhos reais: encontrar versão nova do plugin; substituir por alternativa mantida; contribuir com compatibilidade e testes; ou adiar a atualização do framework com risco documentado e prazo curto.
Usar --force não cria um quinto caminho. Ele apenas pula a verificação. Se o plugin acessa uma API removida na versão 5, a falha reaparecerá durante build ou execução.
Monte uma pequena tabela de decisão com manutenção, compatibilidade, esforço de migração e cobertura de teste. A melhor solução técnica muitas vezes é remover um plugin pequeno, não congelar o ecossistema inteiro por causa dele.
Checklist para encerrar o ERESOLVE
- o pacote conflitante e quem o exige foram identificados;
- as duas faixas de versão foram comparadas;
npm explain,npm lsenpm viewsustentam o diagnóstico;- changelog e guia de migração foram lidos;
- plugin e hospedeiro formam uma combinação suportada;
package-lock.jsonfoi preservado e revisado;npm cifunciona em instalação limpa;- testes, build e inicialização passaram;
--forcee--legacy-peer-depsnão viraram solução permanente;- overrides têm justificativa e plano de remoção;
- logs compartilhados não expõem registro ou caminhos privados.
Documentação primária
- npm — package.json e peerDependencies
- npm — package-lock.json
- npm — comando npm explain
- npm — comando npm ci
- Semantic Versioning 2.0.0
Nota de produção
Rascunho autoral criado para a intenção “como corrigir npm ERR ERESOLVE”. O laboratório usa pacotes locais fictícios para não depender da disponibilidade de versões externas. Conceitos de peer dependency, lockfile e instalação limpa foram conferidos na documentação oficial do npm. Antes de publicar, a revisão humana deve executar o laboratório com a versão de npm suportada pelo artigo e confirmar os links internos.
Camada extra: como tomar uma decisão melhor neste cenário
Um artigo sobre npm ERR! ERESOLVE: como corrigir conflitos de peerDependencies sem quebrar o projeto fica mais útil quando separa a solução imediata da decisão que continua válida depois que a tela, a versão do software ou o dispositivo muda.
O erro **npm ERR! ERESOLVE unable to resolve dependency tree** aparece quando o npm não consegue construir uma árvore de dependências que satisfaça, ao mesmo tempo, as versões exigidas pelo projeto e pelos pacotes instalados. Apagar `node_m A ideia central pode ser testada com quatro perguntas: o que foi observado, qual hipótese explica o sintoma, qual mudança é reversível e qual evidência prova que funcionou. Esse encadeamento evita que uma coincidência seja confundida com causa e torna o procedimento repetível por outra pessoa.
Qualidade de IA precisa de um teste, não de uma impressão
Para npm, Node.js, peerDependencies, JavaScript, escolha três tarefas representativas: uma simples, uma ambígua e uma em que a resposta possa ser conferida em fonte primária. Compare utilidade, rastreabilidade, privacidade, velocidade e quantidade de correção humana necessária. Uma resposta elegante não compensa uma citação inexistente ou uma conclusão que não pode ser reproduzida.
Separe ainda o que pode sair do dispositivo do que deve permanecer local. Dados públicos toleram fluxos diferentes de documentos internos, contratos, informações pessoais ou bases de clientes. A escolha entre processamento local e nuvem deve ser feita pelo risco do conteúdo, não apenas pela conveniência da interface.
Grade de avaliação prática
| Critério | Pergunta | Evidência |
|---|---|---|
| Correção | A resposta bate com a fonte? | Checagem independente |
| Rastreabilidade | É possível localizar de onde veio? | Citação ou trecho verificável |
| Privacidade | Que dado sai do dispositivo? | Política e configuração |
| Esforço | Quanto trabalho humano resta? | Tempo de revisão |
O ponto em que a IA deixa de ajudar
Se a tarefa exige precisão absoluta e a saída não pode ser validada, a automação deve ser limitada a apoio: localizar trechos, organizar opções ou preparar uma primeira versão. A decisão final precisa permanecer com alguém capaz de verificar a fonte e assumir a responsabilidade pelo resultado.
Checklist de fechamento
- Registre o estado inicial antes de alterar qualquer coisa.
- Faça uma mudança por rodada e anote o efeito.
- Teste um caso normal, um caso-limite e o cenário que originalmente falhou.
- Confirme que a solução continua válida depois de reiniciar, reabrir ou repetir o fluxo.
- Guarde uma forma de voltar ao estado anterior quando a alteração for destrutiva.
Esse método acrescenta profundidade sem transformar o artigo em teoria abstrata: o leitor entende por que cada passo existe e como reconhecer quando a situação exige uma decisão diferente.
