denoland/deno · error · TypeError
ERR_INVALID_ARG_VALUE
ERR_INVALID_ARG_VALUE
Error message
The property 'options.recursive' is no longer supported. Received ${inspect(value)} What it means
Node removed the recursive option from fs.rmdir (deprecated since v14.14, hard error in v16+); Deno's polyfill follows suit and throws ERR_INVALID_ARG_VALUE('options.recursive', ..., 'is no longer supported') instead of silently doing a non-recursive rmdir. The check fires before any filesystem operation.
Source
Thrown at ext/node/polyfills/fs.ts:1876
function rmdir(
path: string | Buffer | URL,
options: rmdirOptions,
callback: rmdirCallback,
): void;
function rmdir(
path: string | Buffer | URL,
options: rmdirOptions | rmdirCallback | undefined,
callback?: rmdirCallback,
) {
if (typeof options === "function") {
callback = options;
options = undefined;
}
if (options?.recursive !== undefined) {
// The `recursive` option was deprecated and removed in Node. Throw with a
// clear message rather than silently doing the wrong thing.
throw new ERR_INVALID_ARG_VALUE(
"options.recursive",
options.recursive,
"is no longer supported",
);
}
validateFunction(callback, "cb");
path = getValidatedPathToString(path);
validateRmdirOptions(options);
PromisePrototypeThen(
op_node_rmdir(path),
(_) => callback(),
(err: Error) =>
callback(
denoErrorToNodeError(err, { syscall: "rmdir", path }),
),
);View on GitHub (pinned to 89f33cbef2)
Solutions
- Replace with fs.rm(dir, { recursive: true }, cb) — rm supports recursive removal
- Set recursive: undefined or omit the key entirely if you truly want a non-recursive rmdir
- Audit dependencies for rmdir recursive usage after upgrading Node/Deno
Example fix
// before
fs.rmdir(dir, { recursive: true }, cb); // ERR_INVALID_ARG_VALUE
// after
fs.rm(dir, { recursive: true }, cb); Defensive patterns
Strategy: validation
Validate before calling
const removeDir = (dir: string, recursive: boolean, cb: (e?: Error | null) => void) =>
recursive ? fs.rm(dir, { recursive: true }, cb) : fs.rmdir(dir, cb); Type guard
const hasRecursive = (o: unknown): o is { recursive: boolean } =>
typeof o === 'object' && o !== null && 'recursive' in o && (o as any).recursive !== undefined; Prevention
- Treat rmdir as non-recursive by definition; route all recursive deletion through fs.rm
- Remember recursive: false also throws — only undefined or an absent key passes
- Codemod/grep for 'rmdir' + 'recursive' when upgrading Node-14-era code
When it happens
Trigger: fs.rmdir(dir, { recursive: true }, cb) — including falsy-but-present values like recursive: false? No: only when options.recursive !== undefined, so { recursive: undefined } passes but any defined value throws.
Common situations: Old tutorials and pre-Node-14 code using rmdir for recursive deletion; dependencies that have not been updated for modern Node semantics; CI upgrading from Node 12-era behavior.
Related errors
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/099f68a0b8cb5f67.
Report an issue: GitHub.