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
- Set `write: false` in your build options and instead read the emitted files from the `outputFiles` array returned in the build result.
- Switch to the native node package (`esbuild`) if you actually need filesystem writes, since `hasFS` is true there.
- 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
- Never hardcode write: true in shared code that runs in the browser.
- Read outputFiles from the result instead of relying on disk writes when targeting WASM.
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
- Cannot use the "serve" API in this environment
- Cannot use the "watch" API in this environment
- Failed to download
- Must provide either the "wasmURL" option or the…
- The "analyzeMetafileSync" API only works in node
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 rebuildsView on GitHub (pinned to f6058f8364)