denoland/deno · error · NodeTypeError

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

The "${name}[${i}]" argument must be of type string

What it means

In fs.glob (and fs.promises.glob), options.exclude may be either an array of glob-pattern strings or a predicate function. validateStringArrayOrFunction checks each array element; a non-string element (number, null, undefined, RegExp) throws ERR_INVALID_ARG_TYPE naming options.exclude[i].

Source

Thrown at ext/node/polyfills/_fs/_fs_glob.ts:204

function getRealpathStringSync(path) {
  try {
    return op_require_real_path(path);
  } catch {
    return null;
  }
}

/**
 * @callback validateStringArrayOrFunction
 * @param {*} value
 * @param {string} name
 */
const validateStringArrayOrFunction = hideStackFrames((value, name) => {
  if (ArrayIsArray(value)) {
    for (let i = 0; i < value.length; ++i) {
      if (typeof value[i] !== "string") {
        throw new ERR_INVALID_ARG_TYPE(`${name}[${i}]`, "string", value[i]);
      }
    }
    return;
  }
  if (typeof value !== "function") {
    throw new ERR_INVALID_ARG_TYPE(name, ["string[]", "function"], value);
  }
});

/**
 * @param {string} pattern
 * @param {options} options
 * @returns {Minimatch}
 */
function createMatcher(pattern, options = kEmptyObject) {
  const opts = {
    __proto__: null,
    nocase: isWindows || isMacOS,

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Keep every exclude entry a string glob: ['dist/**', 'coverage/**']
  2. Convert RegExp filters to globs, or use the function form: exclude: (p) => re.test(p)
  3. Sanitize before passing: exclude.filter((x) => typeof x === 'string')

Example fix

// before
fs.glob("**/*.ts", { exclude: ["node_modules", /vendor/] }, cb);

// after
fs.glob("**/*.ts", { exclude: ["node_modules", "vendor/**"] }, cb);
// or the predicate form:
fs.glob("**/*.ts", { exclude: (p) => /vendor/.test(p) }, cb);
Defensive patterns

Strategy: type-guard

Validate before calling

function normalizeExclude(v: unknown): string[] | ((p: string) => boolean) {
  if (typeof v === "function") return v;
  if (Array.isArray(v)) {
    const strs = v.filter((x): x is string => typeof x === "string");
    if (strs.length !== v.length) {
      throw new Error(
        "fs.glob options.exclude must be an array of glob strings or a function; found non-string entries - convert RegExp filters to the function form",
      );
    }
    return strs;
  }
  throw new Error("options.exclude must be string[] or function");
}

Type guard

function isStringArrayOrFunction(v: unknown): v is string[] | ((p: string) => boolean) {
  if (typeof v === "function") return true;
  return Array.isArray(v) && v.every((x) => typeof x === "string");
}

Prevention

When it happens

Trigger: fs.glob('**/*.ts', { exclude: ['node_modules', /build/] }); exclude: ['dist', 42]; arrays built from config where some entries are undefined.

Common situations: Mixing RegExp filters into exclude (it expects glob strings); assembling exclude lists from heterogeneous config; spreading optional arrays that contain holes or nulls.

Related errors


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