evanw/esbuild · critical · Error
Cannot start service: Host version
Error message
Cannot start service: Host version "${ESBUILD_VERSION}" does not match binary version ${quote(binaryVersion)} What it means
On the first packet from the spawned esbuild binary, the JS wrapper compares the binary's self-reported version against the JS-side ESBUILD_VERSION constant (lib/shared/common.ts:622). Any mismatch aborts service startup. This guard detects broken installs where the native binary (from a platform package like @esbuild/linux-x64) and the JS wrapper come from different esbuild releases.
Solutions
- Delete node_modules and the lockfile, then reinstall cleanly so esbuild and all @esbuild/* platform packages align to one version.
- Run your package manager's dedupe (npm dedupe / yarn dedupe / pnpm dedupe) to collapse duplicate esbuild versions.
- Pin esbuild to a single exact version in package.json and ensure transitive deps don't pull in a different one (npm ls esbuild).
- Clear CI caches that snapshot node_modules across version bumps.
Example fix
# before: mismatched versions in lockfile npm ls esbuild # shows multiple versions # after rm -rf node_modules package-lock.json npm install esbuild@latest npm ls esbuild # single version
Defensive patterns
Strategy: try-catch
Validate before calling
import { version as jsVersion } from 'esbuild'
// Fail fast in your own setup if a platform binary is missing/mismatched
import { existsSync } from 'fs'
// Example: sanity-check that the platform package resolves
function preflight() {
try {
require.resolve('@esbuild/linux-x64/bin/esbuild') // adjust to your platform
} catch {
throw new Error('esbuild platform binary not installed; run a clean install')
}
}
preflight() Try / catch
try {
await esbuild.build(opts)
} catch (e) {
if (/does not match binary version/.test(e.message)) {
console.error('esbuild version mismatch detected. Run: rm -rf node_modules package-lock.json && npm install')
process.exit(1)
}
throw e
} Prevention
- Pin esbuild to a single exact version in package.json and run `npm ls esbuild` in CI to detect duplicates.
- Run `npm dedupe` (or pnpm/yarn equivalent) after upgrades.
- Don't cache node_modules across an esbuild version bump in CI; bust the cache on dependency changes.
- After upgrading esbuild, delete node_modules and the lockfile and reinstall fresh.
When it happens
Trigger: Any esbuild API call (build/transform/context) that starts the service when the installed `esbuild` JS package version differs from the installed platform-binary package version. The message prints both versions for diagnosis.
Common situations: A partial/half-upgraded install (lockfile resolved esbuild to one version and @esbuild/<platform> to another); duplicate esbuild copies in a monorepo (hoisting); stale npm/yarn/pnpm cache or PnP mismatch; manually copied esbuild binaries; CI caching node_modules across an upgrade.
Related errors
- Could not find in archive
- Expected but got
- Missing hash for
- Failed to install package
- Invalid gzip data in archive
AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09).
Data as JSON: /api/errors/0b3f6d50902caaf5.
Report an issue: GitHub.
Appendix: source
Thrown at lib/shared/common.ts:623
// cause an unhandled promise rejection. Our caller isn't expecting
// this call to fail and doesn't handle the promise rejection.
}
}
}
let isFirstPacket = true
let handleIncomingPacket = (bytes: Uint8Array<ArrayBuffer>): void => {
// The first packet is a version check
if (isFirstPacket) {
isFirstPacket = false
// Validate the binary's version number to make sure esbuild was installed
// correctly. This check was added because some people have reported
// errors that appear to indicate an incorrect installation.
let binaryVersion = String.fromCharCode(...bytes)
if (binaryVersion !== ESBUILD_VERSION) {
throw new Error(`Cannot start service: Host version "${ESBUILD_VERSION}" does not match binary version ${quote(binaryVersion)}`)
}
return
}
let packet = protocol.decodePacket(bytes) as any
if (packet.isRequest) {
handleRequest(packet.id, packet.value)
}
else {
let callback = responseCallbacks[packet.id]!
delete responseCallbacks[packet.id]
if (packet.value.error) callback(packet.value.error, {})
else callback(null, packet.value)
}
}
View on GitHub (pinned to f6058f8364)