Last updated Sep 8, 2026

New Relic com Bun e Next.js 16: corrigindo ERR_REQUIRE_ESM no Turbopack

Ao instalar o New Relic Node.js Agent em uma aplicação Next.js 16 gerenciada com Bun, o servidor de desenvolvimento pode iniciar e, segundos depois, encerrar com ERR_REQUIRE_ESM. No caso analisado, a falha apareceu quando o Turbopack carregou o transformer do New Relic e resolveu o parser meriyah no formato errado.

O erro completo continha referências semelhantes a:

New Relic for Node.js was unable to bootstrap itself due to an error:

Error [ERR_REQUIRE_ESM]:
require() of ES Module .../meriyah/dist/meriyah.mjs not supported

at @apm-js-collab/code-transformer/lib/transformer.js
at next/dist/server/require-hook.js

Este artigo registra a causa e a solução para tornar o diagnóstico encontrável por quem pesquisar por termos como:

  • New Relic ERR_REQUIRE_ESM;
  • Bun New Relic Next.js;
  • meriyah.mjs not supported;
  • @apm-js-collab/code-transformer meriyah;
  • Next.js 16 Turbopack require ESM.

Outros usuários tiveram problemas semelhantes?

Sim, existem relatos públicos de incompatibilidades da mesma classe envolvendo Next.js 16, Turbopack, aplicações ou monorepos ESM e resolução de dependências com Bun.

Isso não significa que todos os relatos tenham exatamente a mesma cadeia New Relic → code-transformer → meriyah. Significa que ERR_REQUIRE_ESM, externalização de pacotes e diferenças entre o grafo do Bun e o runtime Node.js são problemas reais observados por outros usuários.

Por exemplo:

O caso documentado aqui é uma manifestação específica dessa família de problemas de resolução entre CommonJS e ESM.

Ambiente em que o erro foi reproduzido

A combinação relevante era:

Next.js 16
Turbopack
Bun como package manager
New Relic Node.js Agent 14.x
Node.js 22+
@apm-js-collab/code-transformer
meriyah 6.1.4

O Bun não estava executando a aplicação como runtime em produção. Ele era o gerenciador de pacotes e produzia o layout isolado em node_modules/.bun. O servidor Next.js continuava sendo executado pelo Node.js.

Essa diferença importa: dizer apenas “aplicação Bun” pode esconder se Bun é o runtime, o package manager ou ambos.

O sintoma

O servidor começava normalmente:

▲ Next.js 16 (Turbopack)
✓ Ready
✓ Running next.config.ts

Logo depois, o hook instrumentation.ts tentava importar newrelic. O agente carregava @apm-js-collab/code-transformer, que usa CommonJS:

const { parse } = require("meriyah");

Apesar do uso de require(), o hook de resolução do Next.js selecionava:

meriyah/dist/meriyah.mjs

O componente CommonJS tentava então carregar um módulo ESM de forma síncrona, produzindo:

Error [ERR_REQUIRE_ESM]: require() of ES Module not supported

Sem NEW_RELIC_LICENSE_KEY e NEW_RELIC_APP_NAME, o caminho de bootstrap não era executado e o servidor parecia funcionar. Por isso, testar sem as variáveis reais poderia esconder o defeito.

A causa

O pacote meriyah@6.1.4 publica builds para CommonJS e ESM por meio de exports condicionais:

{
  "exports": {
    "types": "./dist/types/meriyah.d.ts",
    "module-sync": "./dist/meriyah.mjs",
    "require": "./dist/meriyah.cjs",
    "default": "./dist/meriyah.mjs"
  }
}

No fluxo iniciado pelo Turbopack e pelo require-hook do Next.js, a condição module-sync tinha precedência. Como ela apontava para meriyah.mjs, o require("meriyah") feito pelo transformer do New Relic recebia ESM.

O erro citava meriyah, mas dependia da interação entre:

New Relic
  ↓
@apm-js-collab/code-transformer
  ↓ require("meriyah")
Next.js/Turbopack require hook
  ↓ escolhe module-sync
meriyah.mjs
  ↓
ERR_REQUIRE_ESM

Por que apenas serverExternalPackages não resolveu

O primeiro ajuste foi manter o New Relic fora do bundle do servidor:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  serverExternalPackages: ["newrelic"],
};

export default nextConfig;

Isso é apropriado porque o New Relic é um agente do runtime Node.js e precisa observar a aplicação em execução.

Mesmo externalizado, porém, o pacote ainda era carregado por um módulo externo gerado pelo Next.js. O require-hook global continuava participando da resolução das dependências transitivas. Consequentemente, meriyah.mjs ainda era selecionado.

A externalização continuou na solução final, mas não bastava sozinha.

A solução usada com Bun

A correção ficou dividida em duas partes:

  1. declarar newrelic em serverExternalPackages;
  2. aplicar um patch reproduzível pelo Bun em meriyah@6.1.4.

O patch altera apenas a condição de carregamento síncrono:

 "exports": {
   "types": "./dist/types/meriyah.d.ts",
-  "module-sync": "./dist/meriyah.mjs",
+  "module-sync": "./dist/meriyah.cjs",
   "require": "./dist/meriyah.cjs",
   "default": "./dist/meriyah.mjs"
 }

Com isso:

  • require("meriyah") recebe o build CommonJS;
  • imports ESM normais continuam usando o arquivo .mjs;
  • o transformer do New Relic consegue iniciar;
  • o Turbopack continua habilitado;
  • o Bun continua sendo usado como package manager.

Gerando o patch com Bun

A forma reproduzível é usar o fluxo nativo do Bun:

bun patch meriyah@6.1.4

Depois de editar o package.json preparado dentro de node_modules/meriyah:

bun patch --commit node_modules/meriyah

O Bun cria um arquivo semelhante a:

patches/meriyah@6.1.4.patch

E registra o patch no projeto:

{
  "patchedDependencies": {
    "meriyah@6.1.4": "patches/meriyah@6.1.4.patch"
  }
}

Assim a correção é reaplicada em instalações limpas, no CI e no deploy. Editar node_modules sem executar bun patch --commit não seria suficiente, porque a alteração desapareceria na próxima instalação.

Exemplo genérico

Imagine uma loja virtual em Next.js que carrega o New Relic no hook oficial de instrumentação:

export async function register() {
  if (process.env.NEXT_RUNTIME !== "nodejs") return;

  await import("newrelic");
}

Ao executar:

bun install
bun run dev

o agente inicia e carrega um transformer CommonJS. Esse transformer precisa de um parser:

const { parse } = require("meriyah");

Antes do patch:

require("meriyah")
  → meriyah.mjs
  → ERR_REQUIRE_ESM
  → servidor encerrado

Depois do patch:

require("meriyah")
  → meriyah.cjs
  → New Relic inicializado
  → servidor responde normalmente

Não é necessário converter toda a aplicação para CommonJS nem desabilitar o Turbopack. A correção limita-se ao caminho síncrono incompatível.

Como confirmar que o New Relic realmente funciona

A ausência do erro não comprova que a telemetria chegou ao New Relic. A validação usada incluiu:

  1. configurar NEW_RELIC_LICENSE_KEY e NEW_RELIC_APP_NAME;
  2. iniciar o servidor com bun run dev;
  3. aguardar além da janela de conexão do agente;
  4. acessar uma rota e confirmar resposta HTTP 200;
  5. executar typecheck, testes e build;
  6. enviar um evento de log com identificador único;
  7. fazer o flush dos dados pendentes;
  8. localizar o identificador no painel do New Relic.

Exemplo de evento:

newrelic.recordLogEvent({
  message: "New Relic local smoke test",
  level: "INFO",
  environment: "local",
  marker: "unique-smoke-test-id"
});

O teste só deve ser considerado completo quando o evento aparecer no New Relic.

Cuidados

O patch é específico de versão

O patch deve indicar meriyah@6.1.4. Ao atualizar o New Relic ou @apm-js-collab/code-transformer, verifique se a dependência foi atualizada e se a correção ainda é necessária.

Teste uma instalação limpa

Antes de enviar para produção:

bun install --frozen-lockfile
bun run test
bun run build

O objetivo é confirmar que o patch vem do repositório e não de uma edição residual em node_modules.

Não confunda API key com o erro de módulos

Uma license key ausente ou inválida produz problemas de configuração ou conexão. Ela não explica um stack trace apontando para require(), .mjs, meriyah e ERR_REQUIRE_ESM.

Acompanhe as atualizações upstream

Essa solução é uma camada de compatibilidade. O ideal é removê-la quando o mapa de exports da dependência ou o resolvedor do Next.js deixar de produzir a combinação incompatível.

Resumo

Se o New Relic não inicia em um projeto Next.js 16 com Turbopack instalado pelo Bun e o erro menciona:

ERR_REQUIRE_ESM
@apm-js-collab/code-transformer
meriyah/dist/meriyah.mjs
next/dist/server/require-hook

a causa provável é que o carregamento CommonJS está recebendo a exportação ESM de meriyah.

A solução que funcionou foi:

  • externalizar newrelic com serverExternalPackages;
  • mudar a condição module-sync de meriyah@6.1.4 para o build .cjs;
  • versionar a mudança com bun patch;
  • validar o servidor e o envio real de telemetria ao New Relic.