denoland/deno · error · UVWASIError
UVWASI_ENOENT
UVWASI_ENOENT
Error message
uvwasi_init: failed to open preopen "${realPathString}" What it means
Thrown during WASI construction when one of the entries in options.preopens points to a host path that does not exist. Before registering a preopen, the polyfill runs statSync on the mapped real path; if the stat fails for any reason (usually ENOENT, but also EACCES on a parent directory), it raises a UVWASIError with code UVWASI_ENOENT, matching libuvwasi's 'uvwasi_init: failed to open preopen' message.
Source
Thrown at ext/node/polyfills/wasi.ts:195
const value = entry[1];
ArrayPrototypePush(envPairs, [key, String(value)]);
}
if (options.preopens !== undefined) {
validateObject(options.preopens, "options.preopens");
}
const preopens: [string, string][] = [];
if (options.preopens) {
for (
const entry of new SafeArrayIterator(ObjectEntries(options.preopens))
) {
const virtualPath = entry[0];
const realPath = entry[1];
const realPathString = String(realPath);
try {
statSync(realPathString);
} catch {
throw new UVWASIError(
"UVWASI_ENOENT",
`uvwasi_init: failed to open preopen "${realPathString}"`,
);
}
ArrayPrototypePush(preopens, [String(virtualPath), realPathString]);
}
}
if (options.returnOnExit !== undefined) {
validateBoolean(options.returnOnExit, "options.returnOnExit");
}
if (options.stdin !== undefined) {
validateInt32(options.stdin, "options.stdin");
}
if (options.stdout !== undefined) {
validateInt32(options.stdout, "options.stdout");
}View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Verify the mapped directory exists before constructing WASI (see validationCode) and create it with mkdirSync(dir, { recursive: true }) if missing.
- Use absolute paths: `preopens: { '/data': path.resolve('./data') }` so resolution does not depend on cwd.
- Double-check spelling and case of every path in the preopens map against the filesystem.
Example fix
// before
const wasi = new WASI({ version: 'preview1', preopens: { '/data': './data' } });
// after
import { mkdirSync } from 'node:fs';
import path from 'node:path';
const dataDir = path.resolve('./data');
mkdirSync(dataDir, { recursive: true });
const wasi = new WASI({ version: 'preview1', preopens: { '/data': dataDir } }); Defensive patterns
Strategy: validation
Validate before calling
import { statSync, mkdirSync } from 'node:fs';
import path from 'node:path';
const preopens: Record<string, string> = {};
for (const [virtual, raw] of Object.entries(userPreopens)) {
const real = path.resolve(String(raw));
statSync(real); // rethrows a clear ENOENT if missing
// or: mkdirSync(real, { recursive: true });
preopens[virtual] = real;
}
const wasi = new WASI({ version: 'preview1', preopens }); Try / catch
try {
return new WASI({ version: 'preview1', preopens });
} catch (err) {
if ((err as { code?: string }).code === 'UVWASI_ENOENT') {
throw new Error('WASI preopen directory missing — check preopens map paths');
}
throw err;
} Prevention
- Resolve every preopen path to an absolute path with path.resolve before passing it in.
- Create sandbox directories eagerly with mkdirSync(dir, { recursive: true }).
- Never build preopen paths by concatenating possibly-undefined env vars or argv entries.
When it happens
Trigger: `new WASI({ version: 'preview1', preopens: { '/data': './does-not-exist' } })`; preopens built from process.argv or env vars that are unset, so the path becomes 'undefined'; relative paths resolved against an unexpected cwd (worker thread, bundled binary, test runner); a path with a typo or wrong case on case-sensitive filesystems.
Common situations: Running a script from a different working directory than assumed (npm lifecycle scripts, systemd services, Docker WORKDIR changes); sandbox directories that the deploy step was supposed to create but did not; CI checkout paths differing from local ones.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_VALUE
- ERR_WASI_NOT_STARTED
- ERR_WASI_ALREADY_STARTED
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/a99464dc26a33e7d.
Report an issue: GitHub.