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, `ensureServiceIsRunning()` (`lib/npm/browser.ts:67`) throws this when `initializePromise` is set but `longLivedService` is not yet assigned — i.e. you called `initialize()` (which kicked off wasm download/instantiation) but then invoked `build`/`transform`/etc. before `await initialize()` resolved. The service is created only after the worker boots and WebAssembly instantiates.

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 6ff1d8b0d8)

Solutions

  1. Await the promise returned by `initialize` before any other esbuild call: `await esbuild.initialize({ wasmURL })`.
  2. Store the initialize promise and chain every subsequent call off it (e.g. `await initPromise; return esbuild.build(...)`).
  3. Lazy-create the service through a singleton that awaits initialize before exposing build/transform.
  4. Add a regression test that calls your entry function twice quickly to catch the race.

Example fix

// before
import * as esbuild from 'esbuild-wasm'
esbuild.initialize({ wasmURL: '/esbuild.wasm' })
esbuild.transform(ts, { loader: 'ts' }) // throws: not resolved yet

// after
await esbuild.initialize({ wasmURL: '/esbuild.wasm' })
const out = await esbuild.transform(ts, { loader: 'ts' })
Defensive patterns

Strategy: validation

Validate before calling

let ready: Promise<void> | undefined
export function ensureEsbuildReady() {
  if (!ready) ready = esbuild.initialize({ wasmURL })
  return ready
}
// Usage: await ensureEsbuildReady(); then call esbuild.build(...)

Type guard

function isInitializeComplete(svc: typeof esbuild): boolean {
  // No public flag exists; track via your own ready promise.
  return !!ready && /* resolved */ readyThennableSettled
}

Try / catch

try {
  return await esbuild.build(opts)
} catch (e) {
  if (/wait for the promise returned from "initialize"/.test((e as Error).message)) {
    await ensureEsbuildReady()
    return esbuild.build(opts)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling `esbuild.build(...)`, `transform`, `context`, `formatMessages`, or `analyzeMetafile` synchronously between `esbuild.initialize(opts)` and the moment the returned promise resolves. Commonly: forgetting to `await`, calling inside a `.then` chain that races, or fire-and-forget initialize.

Common situations: Top-level code that calls initialize then immediately uses esbuild; React useEffect that calls initialize and then a sibling effect calls transform; missing `await` due to no top-level await; misordering in a script that loads wasm over a slow network.

Related errors


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