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

  1. Use 'utf8' (default) or 'buffer'; for Dirent objects use { withFileTypes: true }
  2. Validate unknown encoding strings with Buffer.isEncoding() before passing them
  3. 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

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


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/cf4e7cc01a592fc9. Report an issue: GitHub.