{"id":"7fa74daca8227a7c","repo":"evanw/esbuild","slug":"the-formatmessagessync-api-only-works-in-node","errorCode":null,"errorMessage":"The \"formatMessagesSync\" API only works in node","messagePattern":"The \"formatMessagesSync\" API only works in node","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/npm/browser.ts","lineNumber":41,"sourceCode":"export const transform: typeof types.transform = (input: string | Uint8Array, options?: types.TransformOptions) =>\n  ensureServiceIsRunning().transform(input, options)\n\nexport const formatMessages: typeof types.formatMessages = (messages, options) =>\n  ensureServiceIsRunning().formatMessages(messages, options)\n\nexport const analyzeMetafile: typeof types.analyzeMetafile = (metafile, options) =>\n  ensureServiceIsRunning().analyzeMetafile(metafile, options)\n\nexport const buildSync: typeof types.buildSync = () => {\n  throw new Error(`The \"buildSync\" API only works in node`)\n}\n\nexport const transformSync: typeof types.transformSync = () => {\n  throw new Error(`The \"transformSync\" API only works in node`)\n}\n\nexport const formatMessagesSync: typeof types.formatMessagesSync = () => {\n  throw new Error(`The \"formatMessagesSync\" API only works in node`)\n}\n\nexport const analyzeMetafileSync: typeof types.analyzeMetafileSync = () => {\n  throw new Error(`The \"analyzeMetafileSync\" API only works in node`)\n}\n\nexport const stop = () => {\n  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}","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/lib/npm/browser.ts#L23-L59","documentation":"The browser entry (`lib/npm/browser.ts:41`) stubs `formatMessagesSync` to throw because formatting messages synchronously requires the native binary via `execFileSync`. The async `formatMessages` works in the browser via the wasm service; the sync variant cannot.","triggerScenarios":"Calling `esbuild.formatMessagesSync(messages, opts)` from code that resolved the browser build of esbuild.","commonSituations":"Pretty-printing esbuild diagnostics synchronously in a browser dev overlay; bundler misconfiguration picking the `browser` field; importing esbuild in a frontend error reporter.","solutions":["Use async `esbuild.formatMessages(messages, opts)`.","Mark esbuild external for browser builds so server code keeps the Node entry.","If formatting must be synchronous in the browser, pre-format messages on the server and ship the strings.","Use `esbuild-wasm` with `initialize` for in-browser async formatting."],"exampleFix":"// before\nconst formatted = esbuild.formatMessagesSync(msgs, { kind: 'error' })\n\n// after\nconst formatted = await esbuild.formatMessages(msgs, { kind: 'error' })","handlingStrategy":"validation","validationCode":"function format(msgs, opts) {\n  return typeof window === 'undefined'\n    ? Promise.resolve(esbuild.formatMessagesSync(msgs, opts))\n    : esbuild.formatMessages(msgs, opts)\n}","typeGuard":"function isBrowser(): boolean {\n  return typeof window !== 'undefined' || (typeof self !== 'undefined' && typeof importScripts === 'function')\n}","tryCatchPattern":"try {\n  return esbuild.formatMessagesSync(msgs, opts)\n} catch (e) {\n  if (/only works in node/.test((e as Error).message)) {\n    return await esbuild.formatMessages(msgs, opts)\n  }\n  throw e\n}","preventionTips":["Default to async formatMessages in code that may run in browsers.","Mark esbuild external in browser-targeted builds.","Pre-format messages server-side when overlay rendering must be synchronous."],"tags":["browser","sync-api","node-only","diagnostics"],"analyzedSha":"6ff1d8b0d8c134e867a397eef39702a223ebef9e","analyzedAt":"2026-08-03T19:42:38.433Z","schemaVersion":2}