evanw/esbuild · error · Error

The "buildSync" API only works in node

Error message

The "buildSync" API only works in node

What it means

esbuild's browser build (`lib/npm/browser.ts`) exports `buildSync` as a function that always throws. The synchronous API exists only on the Node entry point because it relies on `child_process.execFileSync` to run the native binary and block the event loop, which is impossible in a browser main thread. Importing `esbuild` and calling `buildSync` means you are resolving the browser build.

Source

Thrown at lib/npm/browser.ts:33

export let version = ESBUILD_VERSION

export let build: typeof types.build = (options: types.BuildOptions) =>
  ensureServiceIsRunning().build(options)

export let context: typeof types.context = (options: types.BuildOptions) =>
  ensureServiceIsRunning().context(options)

export const transform: typeof types.transform = (input: string | Uint8Array, options?: types.TransformOptions) =>
  ensureServiceIsRunning().transform(input, options)

export const formatMessages: typeof types.formatMessages = (messages, options) =>
  ensureServiceIsRunning().formatMessages(messages, options)

export const analyzeMetafile: typeof types.analyzeMetafile = (metafile, options) =>
  ensureServiceIsRunning().analyzeMetafile(metafile, options)

export const buildSync: typeof types.buildSync = () => {
  throw new Error(`The "buildSync" API only works in node`)
}

export const transformSync: typeof types.transformSync = () => {
  throw new Error(`The "transformSync" API only works in node`)
}

export const formatMessagesSync: typeof types.formatMessagesSync = () => {
  throw new Error(`The "formatMessagesSync" API only works in node`)
}

export const analyzeMetafileSync: typeof types.analyzeMetafileSync = () => {
  throw new Error(`The "analyzeMetafileSync" API only works in node`)
}

export const stop = () => {
  if (stopService) stopService()
  return Promise.resolve()
}

View on GitHub (pinned to 6ff1d8b0d8)

Solutions

  1. Switch to the async `esbuild.build()` (returns a Promise) which is supported in the browser via the wasm service.
  2. Ensure your bundler does not rewrite esbuild to its browser build — mark esbuild as external if you intend to use it only in Node.
  3. If you genuinely need esbuild in the browser, use the `esbuild-wasm` package and call `initialize({ wasmURL })` before async APIs.
  4. Move the `buildSync` call to a Node-only entry point that is never loaded in the browser bundle.

Example fix

// before
const result = esbuild.buildSync({ entryPoints: ['a.ts'], bundle: true })

// after
const result = await esbuild.build({ entryPoints: ['a.ts'], bundle: true })
Defensive patterns

Strategy: validation

Validate before calling

const isBrowser = typeof window !== 'undefined' || typeof self !== 'undefined'
if (isBrowser && typeof (esbuild as any).buildSync === 'function') {
  // will throw — switch to async build
}
// Prefer: detect before invoking
function safeBuild(opts) {
  return isBrowser ? esbuild.build(opts) : Promise.resolve(esbuild.buildSync(opts))
}

Type guard

function supportsSyncApi(): boolean {
  return typeof process !== 'undefined' && !!process.versions?.node && typeof window === 'undefined'
}

Try / catch

try {
  const r = esbuild.buildSync(opts)
} catch (e) {
  if (/only works in node/.test(String((e as Error).message))) {
    return await esbuild.build(opts) // graceful async fallback
  }
  throw e
}

Prevention

When it happens

Trigger: Calling `esbuild.buildSync(options)` after `esbuild` has resolved to `lib/npm/browser.ts` — typically because a bundler (webpack/vite/esbuild itself) targeted the browser field, or because code ran in a browser/worker context.

Common situations: Using esbuild inside a browser-targeted webpack/vite build; importing esbuild in an isomorphic code path that runs in the browser; tooling that auto-selects the `browser` field of package.json; running esbuild in a Cloudflare Worker or Deno browser-like environment.

Related errors


AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03). Data as JSON: /data/errors/06bc8c354ccf15b7.json. Report an issue: GitHub.