{"record":{"id":"eb4ca816621254ad","repo":"denoland/deno","slug":"invalidinput-eb4ca8","errorCode":"InvalidInput","errorMessage":"Can't convert url (\"{}\") to filename.","messagePattern":"Can't convert url \\(\"(.+?)\"\\) to filename\\.","errorType":"error_code","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"libs/cache_dir/local.rs","lineNumber":697,"sourceCode":"      // prevent collisions with a directory of the same name\n      !has_known_extension(part) || !part.ends_with(last_ext)\n    } else {\n      // if any non-ending path part has a known extension, hash it in order to\n      // prevent collisions where a filename has the same name as a directory name\n      has_known_extension(part)\n    };\n\n    // the hash symbol at the start designates a hash for the url part\n    hash_context_specific\n      || part.starts_with('#')\n      || has_forbidden_chars(part)\n      || last_ext.is_none() && FORBIDDEN_WINDOWS_NAMES.contains(part)\n      || part.ends_with('.')\n  }\n\n  // get the base url\n  let Some(base_part) = base_url_to_local_filename_part(url) else {\n    return Err(std::io::Error::new(\n      ErrorKind::InvalidInput,\n      format!(\"Can't convert url (\\\"{}\\\") to filename.\", url),\n    ));\n  };\n\n  // first, try to get the filename of the path\n  let path_segments = url_path_segments(url);\n  let mut parts = std::iter::once(base_part)\n    .chain(path_segments.map(Cow::Borrowed))\n    .collect::<Vec<_>>();\n\n  // push the query parameter onto the last part\n  if let Some(query) = url.query() {\n    let last_part = parts.last_mut().unwrap();\n    let last_part = match last_part {\n      Cow::Borrowed(_) => {\n        *last_part = Cow::Owned(last_part.to_string());\n        match last_part {","sourceCodeStart":679,"sourceCodeEnd":715,"githubUrl":"https://github.com/denoland/deno/blob/336da420f4343cbb1dcbd5eed9d075ff555ed6ee/libs/cache_dir/local.rs#L679-L715","documentation":"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.).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure only http/https URLs are written into the remote cache; route data:/file: URLs to a different loader path.","Sanitize or rename URL path segments that collide with forbidden Windows names (CON, PRN, AUX, NUL, COM1-9, LPT1-9) or end with '.'.","Validate the URL (scheme + host present) before calling cache APIs.","Catch the InvalidInput io::Error and treat the URL as non-cacheable rather than unwrapping."],"exampleFix":"// before\ncache.set(&Url::parse(\"https://host/CON\")?, headers, bytes)?; // forbidden Windows name\n// after\nlet url = Url::parse(\"https://host/const_js\")?; // sanitized segment\nif url.scheme().starts_with(\"http\") {\n  cache.set(&url, headers, bytes)?;\n}","handlingStrategy":"validation","validationCode":"const FORBIDDEN = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\\.|$)/i;\nfunction isLocalCacheSafe(u: URL): boolean {\n  return /^https?:$/.test(u.protocol) && u.hostname !== \"\" &&\n    u.pathname.split(\"/\").every(seg => seg !== \"\" && !seg.endsWith(\".\") && !FORBIDDEN.test(seg));\n}","typeGuard":"function isHttpUrlWithSafeSegments(u: URL): u is URL {\n  return (u.protocol === \"http:\" || u.protocol === \"https:\") &&\n    !u.pathname.split(\"/\").some(s => s === \"\" || s.endsWith(\".\"));\n}","tryCatchPattern":"try {\n  cache.set(url, headers, body);\n} catch (e) {\n  if (e instanceof Deno.errors.InvalidData || e.code === \"InvalidInput\") {\n    console.warn(`skipping non-cacheable url: ${url}`);\n  } else throw e;\n}","preventionTips":["Only insert http/https URLs into the remote HTTP cache.","Sanitize path segments for Windows reserved names and trailing dots.","Don't feed data: URLs from custom loaders into the disk cache.","Treat this error as 'URL not cacheable' and skip rather than crash."],"tags":["cache","url","windows","filesystem"],"backgroundTag":"invalid-url-format","analyzedSha":"336da420f4343cbb1dcbd5eed9d075ff555ed6ee","analyzedAt":"2026-09-11T17:12:50.272Z","contentChangedAt":"2026-09-11T17:12:50.272Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}