evanw/esbuild · error · Error

The "analyzeMetafileSync" API only works in node

Error message

The "analyzeMetafileSync" API only works in node

What it means

The browser entry (`lib/npm/browser.ts:45`) stubs `analyzeMetafileSync` to throw. Analyzing a metafile synchronously requires spawning the native binary; the browser only supports the async variant via the wasm service.

Source

Thrown at lib/npm/browser.ts:45

  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()
}

interface Service {
  build: typeof types.build
  context: typeof types.context
  transform: typeof types.transform
  formatMessages: typeof types.formatMessages
  analyzeMetafile: typeof types.analyzeMetafile
}

let initializePromise: Promise<void> | undefined
let stopService: (() => void) | undefined
let longLivedService: Service | undefined

View on GitHub (pinned to 6ff1d8b0d8)

Solutions

  1. Use the async `esbuild.analyzeMetafile(metafile, opts)`.
  2. Mark esbuild external in the browser bundler config.
  3. Run metafile analysis in a Node build step and write the report to disk for the browser to consume.
  4. Use `esbuild-wasm` with `initialize` for in-browser async analysis.

Example fix

// before
const report = esbuild.analyzeMetafileSync(metafile)

// after
const report = await esbuild.analyzeMetafile(metafile)
Defensive patterns

Strategy: validation

Validate before calling

function analyze(metafile, opts) {
  return typeof window === 'undefined'
    ? Promise.resolve(esbuild.analyzeMetafileSync(metafile, opts))
    : esbuild.analyzeMetafile(metafile, opts)
}

Type guard

function isBrowser(): boolean {
  return typeof window !== 'undefined'
}

Try / catch

try {
  return esbuild.analyzeMetafileSync(metafile, opts)
} catch (e) {
  if (/only works in node/.test((e as Error).message)) {
    return await esbuild.analyzeMetafile(metafile, opts)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling `esbuild.analyzeMetafileSync(metafile, opts)` after the browser build was loaded.

Common situations: Bundle analyzers running in the browser; webpack/vite picking the `browser` field of esbuild; shared metafile-analysis utility loaded into a browser context.

Related errors


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