{"record":{"id":"b3ff80577f282603","repo":"denoland/deno","slug":"invalid-file-path-b3ff80","errorCode":null,"errorMessage":"Invalid file path '{}'","messagePattern":"Invalid file path '(.+?)'","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"cli/util/fs.rs","lineNumber":179,"sourceCode":"/// Gets the total size (in bytes) of a directory.\npub fn dir_size(path: &Path) -> std::io::Result<u64> {\n  let entries = std::fs::read_dir(path)?;\n  let mut total = 0;\n  for entry in entries {\n    let entry = entry?;\n    total += match entry.metadata()? {\n      data if data.is_dir() => dir_size(&entry.path())?,\n      data => data.len(),\n    };\n  }\n  Ok(total)\n}\n\npub fn specifier_from_file_path(\n  path: &Path,\n) -> Result<ModuleSpecifier, AnyError> {\n  ModuleSpecifier::from_file_path(path)\n    .map_err(|_| anyhow!(\"Invalid file path '{}'\", path.display()))\n}\n\n#[derive(Default)]\npub struct FsCleaner {\n  pub files_removed: u64,\n  pub dirs_removed: u64,\n  pub bytes_removed: u64,\n  /// Paths that could not be removed, along with the error encountered. The\n  /// cleaner is best-effort: a single locked or read-only file (for example a\n  /// cache database held open by a running Deno process) should not abort the\n  /// entire clean, so failures are collected here and reported afterwards.\n  pub failed: Vec<(PathBuf, std::io::Error)>,\n  pub progress_guard: Option<UpdateGuard>,\n}\n\nimpl FsCleaner {\n  pub fn new(progress_guard: Option<UpdateGuard>) -> Self {\n    Self {","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/cli/util/fs.rs#L161-L197","documentation":"Shared helper that converts a filesystem Path into a `file://` ModuleSpecifier. `ModuleSpecifier::from_file_path` rejects paths that cannot form a valid file URL — empty paths and non-UTF-8 byte sequences — and the failure is re-wrapped with the offending path printed.","triggerScenarios":"Calling `specifier_from_file_path` (used across CLI tooling) with `Path::new(\"\")` or a path containing invalid UTF-8 on Unix.","commonSituations":"Embedder/library code passing user input straight to PathBuf; paths produced by lossy string conversions; missing empty-input filtering before the call.","solutions":["Validate the path is non-empty and valid UTF-8 before conversion (`path.to_str().is_some()`)","Reject or canonicalize user-supplied paths earlier in the pipeline so only well-formed paths reach this helper","Avoid constructing paths from lossy (`to_string_lossy`) output, which can smuggle in replacement characters"],"exampleFix":"// before\nlet spec = specifier_from_file_path(&PathBuf::from(user_input))?;\n// after\nlet p = PathBuf::from(user_input);\nif p.as_os_str().is_empty() || p.to_str().is_none() {\n  return Err(anyhow!(\"path is empty or not valid UTF-8\"));\n}\nlet spec = specifier_from_file_path(&p)?;","handlingStrategy":"type-guard","validationCode":"// Rust: check before converting\nfn is_urlable_path(p: &Path) -> bool {\n  !p.as_os_str().is_empty() && p.to_str().is_some()\n}\n\nif is_urlable_path(&path) {\n  let spec = specifier_from_file_path(&path)?;\n}","typeGuard":"fn is_urlable_path(p: &Path) -> bool {\n  !p.as_os_str().is_empty() && p.to_str().is_some()\n}","tryCatchPattern":"// Rust: catch and add caller context\nmatch specifier_from_file_path(&path) {\n  Ok(spec) => spec,\n  Err(e) if e.to_string().contains(\"Invalid file path\") => {\n    return Err(anyhow::anyhow!(\"skipping non-URL-able path {}: {e}\", path.display()));\n  }\n  Err(e) => return Err(e),\n}","preventionTips":["Filter empty paths at the argument-parsing boundary","Validate `to_str().is_some()` before any Path -> ModuleSpecifier conversion","Never derive paths from `to_string_lossy` output"],"tags":["filesystem","url","utility","encoding"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}