denoland/deno · error · std::io::Error

InvalidInput

InvalidInput

Error message

Can't convert url ("{}") to filename.

What it means

url_to_local_sub_path builds the local (on-disk) sub-path for a cached remote module in the newer cache layout, using base_url_to_local_filename_part. If the URL's base cannot be converted (unsupported scheme/host shape, or path segments that are forbidden Windows names, empty, or end with '.'), this InvalidInput error is thrown because no safe local path can be derived. It is raised through the Cache API surface (get/set/local_path_for_url/etc.).

Source

Thrown at libs/cache_dir/local.rs:697

      // prevent collisions with a directory of the same name
      !has_known_extension(part) || !part.ends_with(last_ext)
    } else {
      // if any non-ending path part has a known extension, hash it in order to
      // prevent collisions where a filename has the same name as a directory name
      has_known_extension(part)
    };

    // the hash symbol at the start designates a hash for the url part
    hash_context_specific
      || part.starts_with('#')
      || has_forbidden_chars(part)
      || last_ext.is_none() && FORBIDDEN_WINDOWS_NAMES.contains(part)
      || part.ends_with('.')
  }

  // get the base url
  let Some(base_part) = base_url_to_local_filename_part(url) else {
    return Err(std::io::Error::new(
      ErrorKind::InvalidInput,
      format!("Can't convert url (\"{}\") to filename.", url),
    ));
  };

  // first, try to get the filename of the path
  let path_segments = url_path_segments(url);
  let mut parts = std::iter::once(base_part)
    .chain(path_segments.map(Cow::Borrowed))
    .collect::<Vec<_>>();

  // push the query parameter onto the last part
  if let Some(query) = url.query() {
    let last_part = parts.last_mut().unwrap();
    let last_part = match last_part {
      Cow::Borrowed(_) => {
        *last_part = Cow::Owned(last_part.to_string());
        match last_part {

View on GitHub (pinned to 336da420f4)

Solutions

  1. Ensure only http/https URLs are written into the remote cache; route data:/file: URLs to a different loader path.
  2. Sanitize or rename URL path segments that collide with forbidden Windows names (CON, PRN, AUX, NUL, COM1-9, LPT1-9) or end with '.'.
  3. Validate the URL (scheme + host present) before calling cache APIs.
  4. Catch the InvalidInput io::Error and treat the URL as non-cacheable rather than unwrapping.

Example fix

// before
cache.set(&Url::parse("https://host/CON")?, headers, bytes)?; // forbidden Windows name
// after
let url = Url::parse("https://host/const_js")?; // sanitized segment
if url.scheme().starts_with("http") {
  cache.set(&url, headers, bytes)?;
}
Defensive patterns

Strategy: validation

Validate before calling

const FORBIDDEN = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|$)/i;
function isLocalCacheSafe(u: URL): boolean {
  return /^https?:$/.test(u.protocol) && u.hostname !== "" &&
    u.pathname.split("/").every(seg => seg !== "" && !seg.endsWith(".") && !FORBIDDEN.test(seg));
}

Type guard

function isHttpUrlWithSafeSegments(u: URL): u is URL {
  return (u.protocol === "http:" || u.protocol === "https:") &&
    !u.pathname.split("/").some(s => s === "" || s.endsWith("."));
}

Try / catch

try {
  cache.set(url, headers, body);
} catch (e) {
  if (e instanceof Deno.errors.InvalidData || e.code === "InvalidInput") {
    console.warn(`skipping non-cacheable url: ${url}`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling HttpCache set/get/read_modified_time/get_file_url/local_path_for_url with a URL whose scheme isn't http/https or whose host/segments fail sanitization — e.g. "data:text/javascript,...", hostless URLs, or path segments named like CON/NUL or ending in a dot on Windows.

Common situations: Custom loaders injecting data: URLs into the HTTP cache; redirected URLs with odd segments; Windows-reserved filenames coming from remote servers; corrupted redirect chains storing non-remote URLs.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of denoland/deno@336da420f4 (2026-09-11). Data as JSON: /api/errors/eb4ca816621254ad. Report an issue: GitHub.