denoland/deno · error · TypeError

ERR_INVALID_FILE_URL_PATH

ERR_INVALID_FILE_URL_PATH

Error message

File URL path must be absolute

What it means

In the Windows branch of fileURLToPathBuffer, the percent-decoded pathname must be shaped like /<drive-letter>:/rest (e.g. /C:/Users): byte 1 an ASCII letter (case-insensitive), byte 2 a colon. File URLs without a drive letter throw ERR_INVALID_FILE_URL_PATH 'must be absolute', since no absolute Windows path can be formed from them.

Source

Thrown at ext/node/polyfills/url.ts:1488

    TypedArrayPrototypeGetBuffer(u8),
    TypedArrayPrototypeGetByteOffset(u8),
    TypedArrayPrototypeGetByteLength(u8),
  );
  if (hostname !== "") {
    const prefix = Buffer.from("\\\\", "ascii");
    const domain = Buffer.from(domainToUnicode(hostname), "utf8");
    // `concat` is a `node:buffer` static method on `Buffer`
    // deno-lint-ignore deno-internal/prefer-primordials
    return Buffer.concat([prefix, domain, decodedPathname]);
  }
  const letter = decodedPathname[1] | 0x20;
  const sep = decodedPathname[2];
  if (
    letter < CHAR_LOWERCASE_A ||
    letter > CHAR_LOWERCASE_Z || // a..z A..Z
    sep !== 0x3a // :
  ) {
    throw new ERR_INVALID_FILE_URL_PATH("must be absolute", url);
  }
  return TypedArrayPrototypeSubarray(decodedPathname, 1);
}

function getPathFromURLWin(url: URL): string {
  const hostname = url.hostname;
  let pathname = url.pathname;
  for (let n = 0; n < pathname.length; n++) {
    if (pathname[n] === "%") {
      const third = StringPrototypeCodePointAt(pathname, n + 2)! | 0x20;
      if (
        (pathname[n + 1] === "2" && third === 102) || // 2f 2F /
        (pathname[n + 1] === "5" && third === 99) // 5c 5C \
      ) {
        throw new ERR_INVALID_FILE_URL_PATH(
          "must not include encoded \\ or / characters",
          url,
        );

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Only use `{ windows: true }` with drive-letter URLs (file:///C:/...)
  2. Build URLs from real Windows paths with pathToFileURL() so the drive letter is present
  3. Branch on process.platform instead of forcing windows semantics

Example fix

// before
const buf = fileURLToPathBuffer(new URL("file:///tmp/a"), { windows: true }); // throws

// after
import { pathToFileURL } from "node:url";
const url = pathToFileURL("C:/tmp/a"); // carries a drive letter
const buf = fileURLToPathBuffer(url, { windows: true });
Defensive patterns

Strategy: validation

Validate before calling

const u = new URL(input);
if (windows && !/^\/[a-zA-Z]:/.test(u.pathname)) {
  throw new Error("Windows file URLs need a drive letter, e.g. file:///C:/x");
}
return fileURLToPathBuffer(u, { windows });

Type guard

const hasDriveLetter = (u: URL): boolean => /^\/[a-zA-Z]:/.test(u.pathname);

Try / catch

try {
  buf = fileURLToPathBuffer(u, { windows: true });
} catch (e: any) {
  if (e?.code === "ERR_INVALID_FILE_URL_PATH") {
    buf = fileURLToPathBuffer(pathToFileURL(winPath), { windows: true });
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: `fileURLToPathBuffer(new URL('file:///tmp/a'), { windows: true })`; POSIX-shaped file URLs forced through the windows code path; relative `file:../x` URLs.

Common situations: Cross-platform tools forcing `{ windows: true }` to precompute Windows byte paths; build pipelines emitting POSIX file URLs consumed by Windows logic.

Related errors


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