{"record":{"id":"a01188c200365d90","repo":"denoland/deno","slug":"can-t-convert-url-to-filename-a01188","errorCode":null,"errorMessage":"Can't convert url (\"{}\") to filename.","messagePattern":"Can't convert url \\(\"(.+?)\"\\) to filename\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/cache_dir/local.rs","lineNumber":688,"sourceCode":"    } 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 port_separator = \"_\"; // make this shorter with just an underscore\n  let Some(mut base_parts) = base_url_to_filename_parts(url, port_separator)\n  else {\n    return Err(std::io::Error::new(\n      ErrorKind::InvalidInput,\n      format!(\"Can't convert url (\\\"{}\\\") to filename.\", url),\n    ));\n  };\n\n  if base_parts[0] == \"https\" {\n    base_parts.remove(0);\n  } else {\n    let scheme = base_parts.remove(0);\n    base_parts[0] = Cow::Owned(format!(\"{}_{}\", scheme, base_parts[0]));\n  }\n\n  // first, try to get the filename of the path\n  let path_segments = url_path_segments(url);\n  let mut parts = base_parts\n    .into_iter()\n    .chain(path_segments.map(Cow::Borrowed))\n    .collect::<Vec<_>>();","sourceCodeStart":670,"sourceCodeEnd":706,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/libs/cache_dir/local.rs#L670-L706","documentation":"The local (LRU) cache directory computes a storage path from a URL the same way the HTTP cache does: it calls base_url_to_filename_parts (libs/cache_dir/common.rs:13), which only accepts http, https, data and blob schemes. When the scheme is anything else the helper returns None and this InvalidInput io::Error is produced with the offending URL. It guards the on-disk layout of the DENO_DIR local cache from URLs it cannot name deterministically.","triggerScenarios":"Using the LocalLruCache (DENO_DIR/local fast cache) API that derives file names from URLs with a non-http/https/data/blob scheme, e.g. caching a \"file://…\" or custom-protocol resource that the local cache key logic tries to convert via base_url_to_filename_parts.","commonSituations":"Switching a cache from only-remote to mixed local resources; a module loader or extension feeding vendor/custom scheme URLs into the local cache; refactors that changed which URLs reach the local cache; tests with synthetic schemes.","solutions":["Look at the URL in the message and change the caller to pass an http/https/data/blob URL, which are the only schemes the cache naming supports.","If the resource is genuinely local (file:), bypass this cache API and address it by its real filesystem path instead of a URL.","For custom schemes, hash or encode the URL into your own file name instead of routing it through base_url_to_filename_parts."],"exampleFix":"// before\nlet file_path = local_lru_cache.get(&Url::parse(\"asset://logo.png\")?)?; // Err: Can't convert url (\"asset://logo.png\") to filename.\n\n// after\nlet url = Url::parse(\"asset://logo.png\")?;\nif !matches!(url.scheme(), \"http\" | \"https\" | \"data\" | \"blob\") {\n  // handle non-cacheable schemes yourself (e.g. hash the whole URL)\n  return Ok(None);\n}\nlet file_path = local_lru_cache.get(&url)?;","handlingStrategy":"validation","validationCode":"fn can_local_cache_name(url: &url::Url) -> bool {\n  matches!(url.scheme(), \"http\" | \"https\" | \"data\" | \"blob\")\n}\n\nif !can_local_cache_name(&url) {\n  return Ok(None); // skip the local cache for unsupported schemes\n}","typeGuard":null,"tryCatchPattern":"match local_cache.get(&url) {\n  Ok(Some(data)) => { /* hit */ }\n  Ok(None) => { /* miss */ }\n  Err(err) if err.kind() == std::io::ErrorKind::InvalidInput => {\n    // unsupported scheme — fall back to a scheme-appropriate path\n  }\n  Err(err) => return Err(err),\n}","preventionTips":["Route truly local resources by path, not URL, so the URL-keyed caches never see file:/custom schemes.","Add unit tests covering every scheme your loader can produce so a new scheme fails in CI, not in production."],"tags":["url","cache","lru","scheme","invalid-input","deno"],"backgroundTag":"unsupported-url-scheme","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}