{"record":{"id":"d2829f6b83765f9f","repo":"denoland/deno","slug":"err-invalid-arg-type-d2829f","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/_posix.ts","lineNumber":283,"sourceCode":"    } else {\n      // We saw the first non-path separator\n      matchedSlash = false;\n    }\n  }\n\n  if (end === -1) return hasRoot ? \"/\" : \".\";\n  if (hasRoot && end === 1) return \"//\";\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  assertPath(path);\n\n  let start = 0;\n  let end = -1;\n  let matchedSlash = true;\n  let i: number;\n\n  if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n    if (ext.length === path.length && ext === path) return \"\";\n    let extIdx = ext.length - 1;\n    let firstNonSlashEnd = -1;\n    for (i = path.length - 1; i >= 0; --i) {\n      const code = StringPrototypeCharCodeAt(path, i);\n      if (code === CHAR_FORWARD_SLASH) {\n        // If we reached a path separator that was not part of a set of path\n        // separators at the end of the string, stop now\n        if (!matchedSlash) {","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/path/_posix.ts#L265-L301","documentation":"`path.posix.basename(path, ext)` requires the second argument to be a string or undefined. The polyfill throws ERR_INVALID_ARG_TYPE for any other type. `null` throws too, because the default parameter only replaces undefined.","triggerScenarios":"`path.basename(file, null)` from a regex match or indexOf-style lookup that returned null; `path.basename(p, 5)`; passing an options object in place of ext; `path.basename(p, ext)` where ext came from destructured config.","commonSituations":"Extension computed with `String.prototype.match()` that returns null when there is no match. Optional config fields with no default. Porting shell habits where the extension filter is a separate flag.","solutions":["Omit the ext argument when you do not need it.","Null-safe the lookup: `file.match(/\\.[^.]+$/)?.[0] ?? ''`.","Coerce explicitly when coercion is intended: `String(ext)`.","Default destructure the parameter: `function base(p, ext = '')`."],"exampleFix":"// before\nconst ext = file.match(/\\.[^.]+$/); // null when no extension\npath.basename(file, ext);\n\n// after\nconst ext = file.match(/\\.[^.]+$/)?.[0] ?? '';\npath.basename(file, ext);","handlingStrategy":"type-guard","validationCode":"const safeExt = (ext) => (ext == null ? '' : String(ext));\npath.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 your own wrappers: basename(p, ext = '').","Remember null throws while undefined does not — normalize null to undefined or ''."],"tags":["path","basename","posix","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"}