evanw/esbuild · error · Error

Must provide either the "wasmURL" option or the "wasmModule"

Error message

Must provide either the "wasmURL" option or the "wasmModule" option

What it means

The browser `initialize` (`lib/npm/browser.ts:76`) requires the caller to point at the WebAssembly binary, because the browser build has no native executable and no filesystem. You must supply either `wasmURL` (a URL esbuild will fetch) or `wasmModule` (a pre-instantiated `WebAssembly.Module`). Without one, esbuild cannot boot the Go runtime that powers the API.

Source

Thrown at lib/npm/browser.ts:76

  analyzeMetafile: typeof types.analyzeMetafile
}

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

let ensureServiceIsRunning = (): Service => {
  if (longLivedService) return longLivedService
  if (initializePromise) throw new Error('You need to wait for the promise returned from "initialize" to be resolved before calling this')
  throw new Error('You need to call "initialize" before calling this')
}

export const initialize: typeof types.initialize = options => {
  options = common.validateInitializeOptions(options || {})
  let wasmURL = options.wasmURL
  let wasmModule = options.wasmModule
  let useWorker = options.worker !== false
  if (!wasmURL && !wasmModule) throw new Error('Must provide either the "wasmURL" option or the "wasmModule" option')
  if (initializePromise) throw new Error('Cannot call "initialize" more than once')
  initializePromise = startRunningService(wasmURL || '', wasmModule, useWorker)
  initializePromise.catch(() => {
    // Let the caller try again if this fails
    initializePromise = void 0
  })
  return initializePromise
}

const startRunningService = async (wasmURL: string | URL, wasmModule: WebAssembly.Module | undefined, useWorker: boolean): Promise<void> => {
  let worker: {
    onmessage: ((event: any) => void) | null
    postMessage: (data: Uint8Array | ArrayBuffer | WebAssembly.Module) => void
    terminate: () => void
  }

  let rejectAllWith: (error: unknown) => void
  const rejectAllPromise = new Promise(resolve => rejectAllWith = resolve)

View on GitHub (pinned to 6ff1d8b0d8)

Solutions

  1. Pass `wasmURL` pointing at the esbuild.wasm asset: `initialize({ wasmURL: '/esbuild.wasm' })`.
  2. If your bundler supports importing wasm as a Module, pass `wasmModule: await WebAssembly.compile(await fetch(url).then(r => r.arrayBuffer()))`.
  3. For bundlers like Vite, use `?url` import suffix to get the asset URL: `import wasmURL from 'esbuild-wasm/esbuild.wasm?url'`.
  4. Ensure the option object isn't being mutated or stripped by build tooling.

Example fix

// before
import * as esbuild from 'esbuild-wasm'
await esbuild.initialize({})

// after
import wasmURL from 'esbuild-wasm/esbuild.wasm?url'
await esbuild.initialize({ wasmURL })
Defensive patterns

Strategy: validation

Validate before calling

function buildInit(opts: { wasmURL?: string; wasmModule?: WebAssembly.Module }) {
  if (!opts.wasmURL && !opts.wasmModule) {
    throw new Error('initialize requires wasmURL or wasmModule in the browser')
  }
  return esbuild.initialize(opts)
}

Type guard

function hasWasmSource(o: { wasmURL?: unknown; wasmModule?: unknown }): boolean {
  return typeof o.wasmURL === 'string' || o.wasmURL instanceof URL || o.wasmModule instanceof WebAssembly.Module
}

Try / catch

try {
  await esbuild.initialize(opts)
} catch (e) {
  if (/Must provide either/.test((e as Error).message)) {
    await esbuild.initialize({ ...opts, wasmURL: defaultWasmURL })
    return
  }
  throw e
}

Prevention

When it happens

Trigger: Calling `esbuild.initialize()` (or `initialize({})`) with neither `wasmURL` nor `wasmModule` in the browser/esbuild-wasm context.

Common situations: Copy-pasted initialize code missing the option; using a CDN or bundler that already provides the wasm module but forgetting to pass it; migrating from esbuild (Node) to esbuild-wasm without adding the option; bundlers that tree-shake the option object.

Related errors


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