denoland/deno · error · Error
TypeError [ERR_INVALID_OPT_VALUE_ENCODING]: The value "${enc
Error message
TypeError [ERR_INVALID_OPT_VALUE_ENCODING]: The value "${encoding}" is invalid for option "encoding" What it means
readdir's validateEncoding (ext/node/polyfills/_fs/_fs_readdir.ts:135) accepts a falsy encoding or the special value 'buffer' and otherwise requires Buffer.isEncoding(encoding). Any other string throws a plain Error whose text mimics Node's TypeError [ERR_INVALID_OPT_VALUE_ENCODING]. Valid values are the Buffer encodings ('utf8', 'utf-8', 'ascii', 'latin1', 'binary', 'base64', 'base64url', 'hex', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le') plus 'buffer'.
Source
Thrown at ext/node/polyfills/_fs/_fs_readdir.ts:135
}
return sortDirEntries(entries);
}
// Mirrors Node's lib/internal/fs/utils.js getOptions(): a bare string options
// arg is treated as { encoding: <string> }.
function normalizeOptions(
options: readDirOptions | string | null | undefined,
): readDirOptions | null {
if (typeof options === "string") {
return { encoding: options };
}
return options ?? null;
}
function validateEncoding(encoding: string | undefined) {
if (!encoding || encoding === "buffer") return;
if (!Buffer.isEncoding(encoding)) {
throw new Error(
`TypeError [ERR_INVALID_OPT_VALUE_ENCODING]: The value "${encoding}" is invalid for option "encoding"`,
);
}
}
export function readdir(
path: string | Buffer | URL,
options: readDirOptions | string,
callback: readDirCallback,
): void;
export function readdir(
path: string | Buffer | URL,
options: readDirOptions | string,
callback: readDirCallbackDirent,
): void;
export function readdir(path: string | URL, callback: readDirCallback): void;
export function readdir(
path: string | Buffer | URL,View on GitHub (pinned to 89f33cbef2)
Solutions
- Use 'utf8' (default) or 'buffer'; for Dirent objects use { withFileTypes: true }
- Validate unknown encoding strings with Buffer.isEncoding() before passing them
- If the value arrives from config, whitelist it against Buffer.isEncoding and fail early with your own message
Example fix
// before
const entries = await fs.promises.readdir(dir, enc); // enc = 'utf16'
// after
if (enc && enc !== 'buffer' && !Buffer.isEncoding(enc)) throw new TypeError(`bad encoding: ${enc}`);
const entries = await fs.promises.readdir(dir, enc); Defensive patterns
Strategy: validation
Validate before calling
const isValidReaddirEncoding = (enc) =>
enc == null || enc === 'buffer' || (typeof enc === 'string' && Buffer.isEncoding(enc));
if (!isValidReaddirEncoding(enc)) throw new TypeError(`invalid encoding: ${enc}`); Type guard
function isReaddirEncoding(v) {
return v == null || v === 'buffer' || (typeof v === 'string' && Buffer.isEncoding(v));
} Prevention
- Whitelist user/config-supplied encodings with Buffer.isEncoding
- Default to omitting encoding (utf8) unless you need Buffers ('buffer')
- Use withFileTypes for Dirent objects instead of encoding tricks
When it happens
Trigger: fs.readdir(dir, 'utf16', cb); fs.promises.readdir(dir, { encoding: 'unicode' }); forwarding a config-supplied encoding string that was never validated.
Common situations: Typos like 'utf-8' variants ('utf8 ', 'UTF16'), passing an object where a string was expected, or treating a Node-API option name (e.g., 'json') as an fs encoding.
Related errors
- A file exists at the destination: ${destStr}
- ERR_MISSING_ARGS
- No callback function supplied
- ERR_INVALID_ARG_TYPE
- invalid ${name}, must not be infinity or NaN
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/cf4e7cc01a592fc9.
Report an issue: GitHub.