evanw/esbuild · error · Error

You need to wait for the promise returned from "initialize"…

Error message

You need to wait for the promise returned from "initialize" to be resolved before calling this

What it means

In the browser build (lib/npm/browser.ts:65-69), ensureServiceIsRunning() throws this specific message when initialize() has been called (so initializePromise is set) but has not yet resolved (longLivedService is still undefined), and an API method like build/transform is invoked in between. esbuild requires the WASM service to be fully booted before any call because WebAssembly instantiation is asynchronous.

Solutions

  1. Await the promise returned by initialize before any other esbuild call.
  2. Chain subsequent calls in a .then() on initialize if top-level await is unavailable.
  3. Centralize initialization in an async bootstrap function that all esbuild usage goes through.

Example fix

// before
esbuild.initialize({ wasmURL: '/esbuild.wasm' })
esbuild.build({ entryPoints: ['a.ts'] })  // throws

// after
await esbuild.initialize({ wasmURL: '/esbuild.wasm' })
await esbuild.build({ entryPoints: ['a.ts'] })
Defensive patterns

Strategy: validation

Validate before calling

// Track initialization state and never call APIs before it resolves.
let ready: Promise<void>

async function boot() {
  ready = esbuild.initialize({ wasmURL: '/esbuild.wasm' })
  await ready
}

async function safeBuild(opts) {
  if (!ready) throw new Error('esbuild not initialized')
  await ready                       // ensure the service is up
  return esbuild.build(opts)
}

Try / catch

// If you cannot await statically, catch and retry after initialize resolves.
try {
  await esbuild.build(opts)
} catch (e) {
  if (/wait for the promise returned from "initialize"/.test(String(e?.message))) {
    await esbuildInitializePromise      // the promise from initialize()
    await esbuild.build(opts)
  } else {
    throw e
  }
}

Prevention

When it happens

Trigger: Calling esbuild.build(...)/transform(...)/etc. immediately after esbuild.initialize({...}) without awaiting the promise initialize returns, while running the browser/WASM build.

Common situations: Forgetting to await initialize at module top level; sequential statements in non-async code that call initialize then build; refactoring from node (where the service auto-starts) to browser without adding the await.

Related errors


AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09). Data as JSON: /api/errors/cb09308b25be5e3a. Report an issue: GitHub.

Appendix: source

Thrown at lib/npm/browser.ts:67

  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

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
}

View on GitHub (pinned to f6058f8364)