evanw/esbuild · error · Error

Cannot use the "serve" API in this environment

Error message

Cannot use the "serve" API in this environment

What it means

serve() spins up an HTTP server inside esbuild's native binary that serves built output and (optionally) a static servedir. Like watch(), it depends on the Go binary binding to a network socket and a filesystem; in browser/wasm builds (hasFS:false) the guard at lib/shared/common.ts:1080 throws. The wasm runtime has no socket layer to bind.

Source

Thrown at lib/shared/common.ts:1080

        watch: (options = {}) => new Promise((resolve, reject) => {
          if (!streamIn.hasFS) throw new Error(`Cannot use the "watch" API in this environment`)
          const keys: OptionKeys = {}
          const delay = getFlag(options, keys, 'delay', mustBeInteger)
          checkForInvalidFlags(options, keys, `in watch() call`)
          const request: protocol.WatchRequest = {
            command: 'watch',
            key: buildKey,
          }
          if (delay) request.delay = delay
          sendRequest<protocol.WatchRequest, null>(refs, request, error => {
            if (error) reject(new Error(error))
            else resolve(undefined)
          })
        }),

        serve: (options = {}) => new Promise((resolve, reject) => {
          if (!streamIn.hasFS) throw new Error(`Cannot use the "serve" API in this environment`)
          const keys: OptionKeys = {}
          const port = getFlag(options, keys, 'port', mustBeValidPortNumber)
          const host = getFlag(options, keys, 'host', mustBeString)
          const servedir = getFlag(options, keys, 'servedir', mustBeString)
          const keyfile = getFlag(options, keys, 'keyfile', mustBeString)
          const certfile = getFlag(options, keys, 'certfile', mustBeString)
          const fallback = getFlag(options, keys, 'fallback', mustBeString)
          const cors = getFlag(options, keys, 'cors', mustBeObject)
          const onRequest = getFlag(options, keys, 'onRequest', mustBeFunction)
          checkForInvalidFlags(options, keys, `in serve() call`)

          const request: protocol.ServeRequest = {
            command: 'serve',
            key: buildKey,
            onRequest: !!onRequest,
          }
          if (port !== void 0) request.port = port
          if (host !== void 0) request.host = host

View on GitHub (pinned to 6ff1d8b0d8)

Solutions

  1. Run serve() under the Node or Deno native entry (hasFS:true).
  2. In the browser, serve output yourself by reading result.outputFiles and feeding them to your own HTTP layer, or skip the dev-server pattern.
  3. If you only need to inspect output, drop serve() and use build({ write:false }) then read outputFiles.

Example fix

// before (browser wasm)
const ctx = await esbuild.context({ entryPoints: ['app.ts'] });
await ctx.serve({ servedir: '.', port: 8000 });
// after — run under node, or fetch output manually
const res = await esbuild.build({ entryPoints: ['app.ts'], write: false });
serveMyself(res.outputFiles); // your own server
Defensive patterns

Strategy: validation

Validate before calling

const hasFS = typeof process !== 'undefined' && !!process.versions?.node;
if (hasFS) {
  await ctx.serve({ port: 8000, servedir: '.' });
} else {
  throw new Error('serve() not available in this environment; use Node');
}

Type guard

function canServe(): boolean {
  return typeof process !== 'undefined' && typeof process.versions?.node === 'string';
}

Try / catch

try {
  await ctx.serve(opts);
} catch (e) {
  if (/Cannot use the "serve" API/.test(e.message)) {
    // fall back to reading outputFiles and serving yourself
  } else throw e;
}

Prevention

When it happens

Trigger: Calling ctx.serve({ port: 8000, servedir: '.' }) on a context from esbuild-wasm or the browser entrypoint. Calling serve() in Deno wasm mode.

Common situations: Building an in-browser IDE and wanting a 'preview server'. Migrating a Node dev-server script that mixed build + serve into a worker. Trying to serve files from inside a sandboxed edge function.

Related errors


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