denoland/deno · error · ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

The "ext" argument must be of type string. Received ${received}

What it means

`path.win32.basename(path, ext)` requires the second argument to be a string or undefined, and throws ERR_INVALID_ARG_TYPE otherwise. `null` throws because the default parameter only covers undefined. This mirrors the posix basename check.

Source

Thrown at ext/node/polyfills/path/_win32.ts:874

      matchedSlash = false;
    }
  }

  if (end === -1) {
    if (rootEnd === -1) return ".";
    else end = rootEnd;
  }
  return StringPrototypeSlice(path, 0, end);
}

/**
 * Return the last portion of a `path`. Trailing directory separators are ignored.
 * @param path to process
 * @param ext of path directory
 */
function basename(path: string, ext = ""): string {
  if (ext !== undefined && typeof ext !== "string") {
    throw new ERR_INVALID_ARG_TYPE("ext", ["string"], ext);
  }

  assertPath(path);

  let start = 0;
  let end = -1;
  let matchedSlash = true;
  let i: number;

  // Check for a drive letter prefix so as not to mistake the following
  // path separator as an extra separator at the end of the path that can be
  // disregarded
  if (path.length >= 2) {
    const drive = StringPrototypeCharCodeAt(path, 0);
    if (isWindowsDeviceRoot(drive)) {
      if (StringPrototypeCharCodeAt(path, 1) === CHAR_COLON) start = 2;
    }
  }

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Omit the ext argument when you do not need it.
  2. Null-safe the lookup: `file.match(/\.[^.]+$/)?.[0] ?? ''`.
  3. Coerce explicitly with `String(ext)` when coercion is intended.
  4. Default the parameter at your own wrapper: `basename(p, ext = '')`.

Example fix

// before
const ext = file.match(/\.[^.]+$/); // null when no match
path.win32.basename(file, ext);

// after
const ext = file.match(/\.[^.]+$/)?.[0] ?? '';
path.win32.basename(file, ext);
Defensive patterns

Strategy: type-guard

Validate before calling

const safeExt = (ext) => (ext == null ? '' : String(ext));
path.win32.basename(file, safeExt(ext));

Type guard

function isOptionalString(v: unknown): v is string | undefined {
  return v === undefined || typeof v === 'string';
}

Prevention

When it happens

Trigger: `path.win32.basename(file, null)` from a match/lookup that returned null; `path.win32.basename(p, 5)`; passing an object in place of ext. Note `path.basename` on Windows uses this win32 implementation.

Common situations: Extension computed with `String.prototype.match()` returning null. Optional ext parameters with no default. Cross-platform filename handling shared between posix and win32 call sites.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/8dea96adbe261e08. Report an issue: GitHub.