evanw/esbuild · error · Error

The "write" option is unavailable in this environment

Error message

The "write" option is unavailable in this environment

What it means

Thrown when the build option `write` is true but the esbuild service was started without filesystem access (i.e. `streamIn.hasFS` is false). The `write` option tells esbuild to write generated output files directly to the filesystem; that is impossible in environments such as the browser/WASM build where `hasFS` is set to `false` (lib/npm/browser.ts:142). By default `write` defaults to `true` only when the filesystem is available, so this only triggers when a caller explicitly passes `write: true` into the browser/WASM API.

Solutions

  1. Set `write: false` in your build options and instead read the emitted files from the `outputFiles` array returned in the build result.
  2. Switch to the native node package (`esbuild`) if you actually need filesystem writes, since `hasFS` is true there.
  3. Detect the environment before passing `write` and only set it when running under Node.

Example fix

// before (browser/wasm)
await esbuild.build({ entryPoints: ['app.ts'], bundle: true, write: true });
// after
let result = await esbuild.build({ entryPoints: ['app.ts'], bundle: true, write: false });
result.outputFiles.forEach(f => console.log(f.path, f.text));
Defensive patterns

Strategy: validation

Validate before calling

// Before calling build(), ensure write is compatible with the environment
const canWrite = typeof process !== 'undefined' && process.versions && process.versions.node;
const options = { ...opts };
if (!canWrite) options.write = false;
await esbuild.build(options);

Type guard

function supportsFs(): boolean {
  // esbuild sets hasFS true only in the node entry; approximate by node detection
  return typeof process !== 'undefined' && !!process.versions && !!process.versions.node;
}

Prevention

When it happens

Trigger: Calling esbuild's `build()`/`context()` from the browser or WASM package (`esbuild-wasm`) and passing `write: true` (or any truthy `write`) in the options, since `hasFS === false` there.

Common situations: Porting a Node-based esbuild script to the browser; using the WASM variant for in-browser bundling while reusing a config that sets `write: true`; default option resolution differing between the node and browser entry points.

Related errors


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

Appendix: source

Thrown at lib/shared/common.ts:927

  } catch (e) {
    handleError(e, '')
  }

  // "buildOrContext" cannot be written using async/await due to "buildSync"
  // and must be written in continuation-passing style instead
  function buildOrContextContinue(requestPlugins: protocol.BuildPlugin[] | null, runOnEndCallbacks: RunOnEndCallbacks, scheduleOnDisposeCallbacks: () => void) {
    const writeDefault = streamIn.hasFS
    const {
      entries,
      flags,
      write,
      stdinContents,
      stdinResolveDir,
      absWorkingDir,
      nodePaths,
      mangleCache,
    } = flagsForBuildOptions(callName, options, isTTY, buildLogLevelDefault, writeDefault)
    if (write && !streamIn.hasFS) throw new Error(`The "write" option is unavailable in this environment`)

    // Construct the request
    const request: protocol.BuildRequest = {
      command: 'build',
      key: buildKey,
      entries,
      flags,
      write,
      stdinContents,
      stdinResolveDir,
      absWorkingDir: absWorkingDir || defaultWD,
      nodePaths,
      context: isContext,
    }
    if (requestPlugins) request.plugins = requestPlugins
    if (mangleCache) request.mangleCache = mangleCache

    // Factor out response handling so it can be reused for rebuilds

View on GitHub (pinned to f6058f8364)