denoland/deno · error · Error
Empty filepath.
Error message
Empty filepath.
What it means
pathDirname is an internal helper of Deno's CommonJS compat layer (ext/node/polyfills/01_require.js); it throws this generic Error when the filepath handed to it is null or undefined. Note the asymmetry: an empty string returns '.', so only nullish values throw. End users normally hit it when CJS module resolution produced no filename - a malformed require target or a gap in the polyfill machinery - not through a public API they called directly.
Source
Thrown at ext/node/polyfills/01_require.js:511
}
setupBuiltinModules();
// Loading node:module has to bootstrap node:process. `_next_tick.ts`'s
// `nextTick()` returns without queueing anything until `enableNextTick()` runs,
// and that only happens inside `__bootstrapNodeProcess()` (node:process's
// deferred trigger). Anything reaching `process.nextTick` before then - e.g.
// `_events.mjs`'s `addCatch`, which routes a rejected handler promise to the
// `error` event under `captureRejections` - silently loses its callback.
//
// This used to happen by accident: the eager `vm.js` load above did
// `createLazyLoader("node:process")()` at its module body. Now that the builtin
// map is lazy, say it on purpose. node:process's closure is ~7 modules and
// every CommonJS entry point pulls it in anyway.
core.createLazyLoader("node:process")();
function pathDirname(filepath) {
if (filepath == null) {
throw new Error("Empty filepath.");
} else if (filepath === "") {
return ".";
}
return op_require_path_dirname(filepath);
}
function pathResolve(...args) {
return op_require_path_resolve(args);
}
const nativeModulePolyfill = new SafeMap();
const relativeResolveCache = ObjectCreate(null);
let requireDepth = 0;
let statCache = null;
let mainModule = null;
let hasBrokenOnInspectBrk = false;
let hasInspectBrk = false;View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Upgrade Deno - node/require interop fixes land in nearly every release
- Reproduce with a minimal require('the-package') and confirm the specifier is a non-empty, valid string
- If it originates from your own module hooks, make sure resolve hooks always return a real URL and load hooks a real filename
Example fix
// before (custom hook returning a malformed result)
registerHooks({
resolve(spec, ctx, next) {
if (spec.startsWith('virtual:')) return; // undefined filename leaks downstream
return next(spec, ctx);
},
});
// after
registerHooks({
resolve(spec, ctx, next) {
if (spec.startsWith('virtual:')) {
return { shortCircuit: true, url: pathToFileURL(spec.slice(8)).href };
}
return next(spec, ctx);
},
}); Defensive patterns
Strategy: try-catch
Validate before calling
function requireSafe(id: string): unknown {
if (typeof id !== 'string' || id.length === 0) {
throw new TypeError(`require() needs a non-empty specifier, got: ${String(id)}`);
}
return require(id);
} Type guard
function isNonEmptyPath(p: unknown): p is string {
return typeof p === 'string' && p.length > 0;
} Try / catch
try {
const mod = require(specifier);
} catch (e) {
if (e instanceof Error && e.message === 'Empty filepath.') {
// internal CJS resolution produced no filename: log specifier and report upstream
throw new Error(`module resolution returned no path for '${specifier}' (Deno CJS interop)`);
}
throw e;
} Prevention
- Keep Deno updated - node/require interop gaps are fixed continuously
- Never pass possibly-null path or specifier values into require-based loaders
- When writing registerHooks hooks, always return well-formed URLs/filenames from every path
When it happens
Trigger: A require() whose specifier resolves to a nullish filename inside the CJS loader; custom resolve/load hooks returning malformed results that leave filename unset; interplay between the eager builtin-map loading and a package expecting a path.
Common situations: Bundled npm packages exercising corner cases of Deno's require polyfill; registerHooks-based loaders returning bad URLs; older Deno versions with resolution gaps that were fixed later.
Related errors
- Module already loaded
- Unknown built-in module
- resolve hook must return { shortCircuit: true } or call next
- load hook must return { shortCircuit: true } or call nextLoa
- Using cpu-features module is currently not supported
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/7fb62f634a272196.
Report an issue: GitHub.