{"id":"cb09308b25be5e3a","repo":"evanw/esbuild","slug":"you-need-to-wait-for-the-promise-returned-from-in","errorCode":null,"errorMessage":"You need to wait for the promise returned from \"initialize\" to be resolved before calling this","messagePattern":"You need to wait for the promise returned from \"initialize\" to be resolved before calling this","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/npm/browser.ts","lineNumber":67,"sourceCode":"  if (stopService) stopService()\n  return Promise.resolve()\n}\n\ninterface Service {\n  build: typeof types.build\n  context: typeof types.context\n  transform: typeof types.transform\n  formatMessages: typeof types.formatMessages\n  analyzeMetafile: typeof types.analyzeMetafile\n}\n\nlet initializePromise: Promise<void> | undefined\nlet stopService: (() => void) | undefined\nlet longLivedService: Service | undefined\n\nlet ensureServiceIsRunning = (): Service => {\n  if (longLivedService) return longLivedService\n  if (initializePromise) throw new Error('You need to wait for the promise returned from \"initialize\" to be resolved before calling this')\n  throw new Error('You need to call \"initialize\" before calling this')\n}\n\nexport const initialize: typeof types.initialize = options => {\n  options = common.validateInitializeOptions(options || {})\n  let wasmURL = options.wasmURL\n  let wasmModule = options.wasmModule\n  let useWorker = options.worker !== false\n  if (!wasmURL && !wasmModule) throw new Error('Must provide either the \"wasmURL\" option or the \"wasmModule\" option')\n  if (initializePromise) throw new Error('Cannot call \"initialize\" more than once')\n  initializePromise = startRunningService(wasmURL || '', wasmModule, useWorker)\n  initializePromise.catch(() => {\n    // Let the caller try again if this fails\n    initializePromise = void 0\n  })\n  return initializePromise\n}\n","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/lib/npm/browser.ts#L49-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Await the promise returned by `initialize` before any other esbuild call: `await esbuild.initialize({ wasmURL })`.","Store the initialize promise and chain every subsequent call off it (e.g. `await initPromise; return esbuild.build(...)`).","Lazy-create the service through a singleton that awaits initialize before exposing build/transform.","Add a regression test that calls your entry function twice quickly to catch the race."],"exampleFix":"// before\nimport * as esbuild from 'esbuild-wasm'\nesbuild.initialize({ wasmURL: '/esbuild.wasm' })\nesbuild.transform(ts, { loader: 'ts' }) // throws: not resolved yet\n\n// after\nawait esbuild.initialize({ wasmURL: '/esbuild.wasm' })\nconst out = await esbuild.transform(ts, { loader: 'ts' })","handlingStrategy":"validation","validationCode":"let ready: Promise<void> | undefined\nexport function ensureEsbuildReady() {\n  if (!ready) ready = esbuild.initialize({ wasmURL })\n  return ready\n}\n// Usage: await ensureEsbuildReady(); then call esbuild.build(...)","typeGuard":"function isInitializeComplete(svc: typeof esbuild): boolean {\n  // No public flag exists; track via your own ready promise.\n  return !!ready && /* resolved */ readyThennableSettled\n}","tryCatchPattern":"try {\n  return await esbuild.build(opts)\n} catch (e) {\n  if (/wait for the promise returned from \"initialize\"/.test((e as Error).message)) {\n    await ensureEsbuildReady()\n    return esbuild.build(opts)\n  }\n  throw e\n}","preventionTips":["Always `await esbuild.initialize(...)` before any other esbuild call.","Centralize initialization behind a singleton that returns the ready promise.","Chain every API call off the same ready promise.","Add a unit test that calls your entry point before initialize resolves."],"tags":["browser","lifecycle","async","initialize","race-condition"],"analyzedSha":"6ff1d8b0d8c134e867a397eef39702a223ebef9e","analyzedAt":"2026-08-03T19:42:38.433Z","schemaVersion":2}