denoland/deno · error · anyhow::Error
Invalid file path '{}'
Error message
Invalid file path '{}' What it means
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.
Source
Thrown at cli/util/fs.rs:179
/// Gets the total size (in bytes) of a directory.
pub fn dir_size(path: &Path) -> std::io::Result<u64> {
let entries = std::fs::read_dir(path)?;
let mut total = 0;
for entry in entries {
let entry = entry?;
total += match entry.metadata()? {
data if data.is_dir() => dir_size(&entry.path())?,
data => data.len(),
};
}
Ok(total)
}
pub fn specifier_from_file_path(
path: &Path,
) -> Result<ModuleSpecifier, AnyError> {
ModuleSpecifier::from_file_path(path)
.map_err(|_| anyhow!("Invalid file path '{}'", path.display()))
}
#[derive(Default)]
pub struct FsCleaner {
pub files_removed: u64,
pub dirs_removed: u64,
pub bytes_removed: u64,
/// Paths that could not be removed, along with the error encountered. The
/// cleaner is best-effort: a single locked or read-only file (for example a
/// cache database held open by a running Deno process) should not abort the
/// entire clean, so failures are collected here and reported afterwards.
pub failed: Vec<(PathBuf, std::io::Error)>,
pub progress_guard: Option<UpdateGuard>,
}
impl FsCleaner {
pub fn new(progress_guard: Option<UpdateGuard>) -> Self {
Self {View on GitHub (pinned to 89f33cbef2)
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
Example fix
// before
let spec = specifier_from_file_path(&PathBuf::from(user_input))?;
// after
let p = PathBuf::from(user_input);
if p.as_os_str().is_empty() || p.to_str().is_none() {
return Err(anyhow!("path is empty or not valid UTF-8"));
}
let spec = specifier_from_file_path(&p)?; Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: check before converting
fn is_urlable_path(p: &Path) -> bool {
!p.as_os_str().is_empty() && p.to_str().is_some()
}
if is_urlable_path(&path) {
let spec = specifier_from_file_path(&path)?;
} Type guard
fn is_urlable_path(p: &Path) -> bool {
!p.as_os_str().is_empty() && p.to_str().is_some()
} Try / catch
// Rust: catch and add caller context
match specifier_from_file_path(&path) {
Ok(spec) => spec,
Err(e) if e.to_string().contains("Invalid file path") => {
return Err(anyhow::anyhow!("skipping non-URL-able path {}: {e}", path.display()));
}
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: Calling `specifier_from_file_path` (used across CLI tooling) with `Path::new("")` or a path containing invalid UTF-8 on Unix.
Common situations: Embedder/library code passing user input straight to PathBuf; paths produced by lossy string conversions; missing empty-input filtering before the call.
Related errors
- Unable to construct URL from the path of cwd: {}
- Unexpected third argument to Deno.bench()
- BenchContext::end() has already been invoked
- ${prefix}Linter plugin must be an object
- Request url protocol must be 'http:' or 'https:': received '
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/b3ff80577f282603.
Report an issue: GitHub.