{"record":{"id":"8dea96adbe261e08","repo":"denoland/deno","slug":"err-invalid-arg-type-8dea96","errorCode":"ERR_INVALID_ARG_TYPE","errorMessage":"The \"ext\" argument must be of type string. Received ${received}","messagePattern":"The \"ext\" argument must be of type string\\. Received (.+?)","errorType":"exception","errorClass":"ERR_INVALID_ARG_TYPE","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/path/_win32.ts","lineNumber":874,"sourceCode":"      matchedSlash = false;\n    }\n  }\n\n  if (end === -1) {\n    if (rootEnd === -1) return \".\";\n    else end = rootEnd;\n  }\n  return StringPrototypeSlice(path, 0, end);\n}\n\n/**\n * Return the last portion of a `path`. Trailing directory separators are ignored.\n * @param path to process\n * @param ext of path directory\n */\nfunction basename(path: string, ext = \"\"): string {\n  if (ext !== undefined && typeof ext !== \"string\") {\n    throw new ERR_INVALID_ARG_TYPE(\"ext\", [\"string\"], ext);\n  }\n\n  assertPath(path);\n\n  let start = 0;\n  let end = -1;\n  let matchedSlash = true;\n  let i: number;\n\n  // Check for a drive letter prefix so as not to mistake the following\n  // path separator as an extra separator at the end of the path that can be\n  // disregarded\n  if (path.length >= 2) {\n    const drive = StringPrototypeCharCodeAt(path, 0);\n    if (isWindowsDeviceRoot(drive)) {\n      if (StringPrototypeCharCodeAt(path, 1) === CHAR_COLON) start = 2;\n    }\n  }","sourceCodeStart":856,"sourceCodeEnd":892,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/path/_win32.ts#L856-L892","documentation":"`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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Omit the ext argument when you do not need it.","Null-safe the lookup: `file.match(/\\.[^.]+$/)?.[0] ?? ''`.","Coerce explicitly with `String(ext)` when coercion is intended.","Default the parameter at your own wrapper: `basename(p, ext = '')`."],"exampleFix":"// before\nconst ext = file.match(/\\.[^.]+$/); // null when no match\npath.win32.basename(file, ext);\n\n// after\nconst ext = file.match(/\\.[^.]+$/)?.[0] ?? '';\npath.win32.basename(file, ext);","handlingStrategy":"type-guard","validationCode":"const safeExt = (ext) => (ext == null ? '' : String(ext));\npath.win32.basename(file, safeExt(ext));","typeGuard":"function isOptionalString(v: unknown): v is string | undefined {\n  return v === undefined || typeof v === 'string';\n}","tryCatchPattern":null,"preventionTips":["Use null-safe extraction for computed extensions: match(...)?.[0] ?? ''.","Default the ext parameter in wrappers around basename.","Remember null throws while undefined does not — normalize before the call."],"tags":["path","basename","win32","invalid-argument","node-compat"],"backgroundTag":"invalid-argument-type","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}