{"record":{"id":"a49fc91ad8cfb2a8","repo":"denoland/deno","slug":"host-must-be-empty","errorCode":null,"errorMessage":"Host must be empty","messagePattern":"Host must be empty","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/00_infra.js","lineNumber":365,"sourceCode":"  p = StringPrototypeReplace(p, PERCENT_RE, \"%25\");\n  let path = decodeURIComponent(p);\n  if (url.hostname != \"\") {\n    // Note: The `URL` implementation guarantees that the drive letter and\n    // hostname are mutually exclusive. Otherwise it would not have been valid\n    // to append the hostname and path like this.\n    path = `\\\\\\\\${url.hostname}${path}`;\n  }\n  return path;\n}\n\n// Keep in sync with `fromFileUrl()` in `std/path/posix.ts`.\n/**\n * @param {URL} url\n * @returns {string}\n */\nfunction pathFromURLPosix(url) {\n  if (url.hostname !== \"\") {\n    throw new TypeError(\"Host must be empty\");\n  }\n\n  return decodeURIComponent(\n    StringPrototypeReplace(url.pathname, PERCENT_RE, \"%25\"),\n  );\n}\n\nfunction pathFromURL(pathOrUrl) {\n  if (ObjectPrototypeIsPrototypeOf(URLPrototype, pathOrUrl)) {\n    if (pathOrUrl.protocol != \"file:\") {\n      throw new TypeError(\"Must be a file URL\");\n    }\n\n    return core.build.os == \"windows\"\n      ? pathFromURLWin32(pathOrUrl)\n      : pathFromURLPosix(pathOrUrl);\n  }\n  return pathOrUrl;","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/00_infra.js#L347-L383","documentation":"pathFromURLPosix (ext/web/00_infra.js:365) converts file:// URLs to POSIX paths and requires an empty hostname. A file URL with a host (file://server/share/file) is a UNC-style reference; on POSIX it has no path equivalent, so Deno throws TypeError('Host must be empty'). On Windows, pathFromURLWin32 instead maps the hostname into a \\\\server\\\\path prefix, so the same URL works there.","triggerScenarios":"Passing new URL('file://nas/share/file.txt') to any Deno fs/path API that accepts a path or file URL (routed through pathFromURL) while running on Linux/macOS; cross-platform code that builds host-bearing file URLs unconditionally.","commonSituations":"UNC paths received from Windows systems and used verbatim on POSIX; config files storing file://host/... URLs; tests with hardcoded Windows file URLs running on Linux CI; strings like 'file://localhost/tmp/x' where even 'localhost' counts as a host.","solutions":["Use a host-less absolute file URL: new URL('file:///mnt/nas/file.txt')","Convert host-based URLs to the mounted POSIX path yourself (strip hostname, prefix the mount point)","Branch on Deno.build.os and only use host-bearing file URLs on Windows"],"exampleFix":"// before (POSIX)\nconst path = new URL('file://nas/share/data.bin');\nDeno.readFileSync(path); // TypeError: Host must be empty\n\n// after (POSIX)\nconst path = new URL('file:///mnt/nas/data.bin');\nDeno.readFileSync(path);","handlingStrategy":"validation","validationCode":"if (url.protocol !== \"file:\") throw new TypeError(\"Must be a file URL\");\nif (Deno.build.os !== \"windows\" && url.hostname !== \"\") {\n  throw new TypeError(`file URL host '${url.hostname}' has no POSIX path; mount it first`);\n}","typeGuard":"function isHostlessFileUrl(u: URL): boolean {\n  return u.protocol === \"file:\" && u.hostname === \"\";\n}","tryCatchPattern":"try {\n  path = pathFromFileUrl(url);\n} catch (e) {\n  if (e instanceof TypeError && e.message === \"Host must be empty\") {\n    // map UNC-style URL to a mounted POSIX path yourself\n    path = `/mnt/${url.hostname}${decodeURIComponent(url.pathname)}`;\n  } else {\n    throw e;\n  }\n}","preventionTips":["Always build file URLs with three slashes (file:///abs/path) on POSIX","Convert incoming UNC paths to mounted paths before constructing URLs","Run cross-platform tests that include host-bearing file URLs on every OS"],"tags":["file-url","path","posix","cross-platform","fs"],"backgroundTag":"file-url-conversion","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}