evanw/esbuild · error · Error
The esbuild JavaScript API cannot be bundled. Please mark…
Error message
The esbuild JavaScript API cannot be bundled. Please mark the "esbuild" package as external so it's not included in the bundle.
More information: The file containing the code for esbuild's JavaScript API (${__filename}) does not appear to be inside the esbuild package on the file system, which usually means that the esbuild package was bundled into another file. This is problematic because the API needs to run a binary executable inside the esbuild package which is located using a relative path from the API code to the executable. If the esbuild package is bundled, the relative path will be incorrect and the executable won't be found. What it means
esbuildCommandAndArgs (lib/npm/node.ts:51) checks whether the currently-executing file looks like it still lives inside the esbuild package (basename 'main.js' inside a dir named 'lib'). If not, it concludes the esbuild JS API was bundled into another file by a tool like webpack/esbuild/rollup. This is fatal because esbuild locates its native binary via a path relative to the API source file; once bundled, that relative path is wrong and the binary cannot be found. esbuild deliberately fails early with an explanatory message rather than a cryptic ENOENT later.
Solutions
- Mark 'esbuild' (and '@esbuild/*') as external in your bundler config so it is required at runtime from node_modules.
- Require/import esbuild lazily at runtime instead of bundling it.
- If you must relocate the binary, set ESBUILD_BINARY_PATH to an absolute path to the native binary.
Example fix
// before (esbuild bundling a tool that itself uses esbuild)
build({ entryPoints: ['src/cli.ts'], bundle: true, outfile: 'dist/cli.js' })
// after
build({
entryPoints: ['src/cli.ts'],
bundle: true,
outfile: 'dist/cli.js',
external: ['esbuild'],
}) Defensive patterns
Strategy: validation
Validate before calling
// Fail the bundler build early if esbuild is not marked external.
const requiredExternals = ['esbuild']
const actualExternals = config.external || []
const missing = requiredExternals.filter(e => !actualExternals.includes(e))
if (missing.length) {
throw new Error(`Mark these as external to avoid bundling esbuild: ${missing.join(', ')}`)
} Prevention
- Always list 'esbuild' (and any '@esbuild/*') in your bundler's `external`.
- Require esbuild lazily at runtime from node_modules rather than bundling it.
- If relocating the binary, set ESBUILD_BINARY_PATH to an absolute path.
When it happens
Trigger: Bundling a tool/library that imports esbuild (so lib/npm/node.ts gets inlined into a dist bundle) without marking 'esbuild' as external, then running the bundle, which calls build/transform and hits esbuildCommandAndArgs.
Common situations: Authoring a CLI that wraps esbuild and shipping a bundled dist; serverless framework bundling that includes esbuild; esbuild used inside another bundler's plugin without externalization; monorepo build pipelines that pre-bundle tooling.
Related errors
- Duplicate source found in source map
- Expected but got
- Missing hash for
- The "esbuild" package cannot be installed because
- Unsupported platform
AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09).
Data as JSON: /api/errors/31c34a781859af71.
Report an issue: GitHub.
Appendix: source
Thrown at lib/npm/node.ts:55
+major < 12 || (+major === 12 && +minor < 17)
// >=v13.0.0 && <v13.13.0 also does not work
|| (+major === 13 && +minor < 13)
) {
worker_threads = void 0
}
}
// This should only be true if this is our internal worker thread. We want this
// library to be usable from other people's worker threads, so we should not be
// checking for "isMainThread".
let isInternalWorkerThread = worker_threads?.workerData?.esbuildVersion === ESBUILD_VERSION
let esbuildCommandAndArgs = (): [string, string[]] => {
// Try to have a nice error message when people accidentally bundle esbuild
// without providing an explicit path to the binary, or when using WebAssembly.
if ((!ESBUILD_BINARY_PATH || WASM) && (path.basename(__filename) !== 'main.js' || path.basename(__dirname) !== 'lib')) {
throw new Error(
`The esbuild JavaScript API cannot be bundled. Please mark the "esbuild" ` +
`package as external so it's not included in the bundle.\n` +
`\n` +
`More information: The file containing the code for esbuild's JavaScript ` +
`API (${__filename}) does not appear to be inside the esbuild package on ` +
`the file system, which usually means that the esbuild package was bundled ` +
`into another file. This is problematic because the API needs to run a ` +
`binary executable inside the esbuild package which is located using a ` +
`relative path from the API code to the executable. If the esbuild package ` +
`is bundled, the relative path will be incorrect and the executable won't ` +
`be found.`)
}
if (WASM) {
return ['node', [path.join(__dirname, '..', 'bin', 'esbuild')]]
} else {
const { binPath, isWASM } = generateBinPath()
if (isWASM) {View on GitHub (pinned to f6058f8364)