denoland/deno · error · TypeError

Host must be empty

Error message

Host must be empty

What it means

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.

Source

Thrown at ext/web/00_infra.js:365

  p = StringPrototypeReplace(p, PERCENT_RE, "%25");
  let path = decodeURIComponent(p);
  if (url.hostname != "") {
    // Note: The `URL` implementation guarantees that the drive letter and
    // hostname are mutually exclusive. Otherwise it would not have been valid
    // to append the hostname and path like this.
    path = `\\\\${url.hostname}${path}`;
  }
  return path;
}

// Keep in sync with `fromFileUrl()` in `std/path/posix.ts`.
/**
 * @param {URL} url
 * @returns {string}
 */
function pathFromURLPosix(url) {
  if (url.hostname !== "") {
    throw new TypeError("Host must be empty");
  }

  return decodeURIComponent(
    StringPrototypeReplace(url.pathname, PERCENT_RE, "%25"),
  );
}

function pathFromURL(pathOrUrl) {
  if (ObjectPrototypeIsPrototypeOf(URLPrototype, pathOrUrl)) {
    if (pathOrUrl.protocol != "file:") {
      throw new TypeError("Must be a file URL");
    }

    return core.build.os == "windows"
      ? pathFromURLWin32(pathOrUrl)
      : pathFromURLPosix(pathOrUrl);
  }
  return pathOrUrl;

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use a host-less absolute file URL: new URL('file:///mnt/nas/file.txt')
  2. Convert host-based URLs to the mounted POSIX path yourself (strip hostname, prefix the mount point)
  3. Branch on Deno.build.os and only use host-bearing file URLs on Windows

Example fix

// before (POSIX)
const path = new URL('file://nas/share/data.bin');
Deno.readFileSync(path); // TypeError: Host must be empty

// after (POSIX)
const path = new URL('file:///mnt/nas/data.bin');
Deno.readFileSync(path);
Defensive patterns

Strategy: validation

Validate before calling

if (url.protocol !== "file:") throw new TypeError("Must be a file URL");
if (Deno.build.os !== "windows" && url.hostname !== "") {
  throw new TypeError(`file URL host '${url.hostname}' has no POSIX path; mount it first`);
}

Type guard

function isHostlessFileUrl(u: URL): boolean {
  return u.protocol === "file:" && u.hostname === "";
}

Try / catch

try {
  path = pathFromFileUrl(url);
} catch (e) {
  if (e instanceof TypeError && e.message === "Host must be empty") {
    // map UNC-style URL to a mounted POSIX path yourself
    path = `/mnt/${url.hostname}${decodeURIComponent(url.pathname)}`;
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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