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

  1. Verify the mapped directory exists before constructing WASI (see validationCode) and create it with mkdirSync(dir, { recursive: true }) if missing.
  2. Use absolute paths: `preopens: { '/data': path.resolve('./data') }` so resolution does not depend on cwd.
  3. 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

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


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/a99464dc26a33e7d. Report an issue: GitHub.