denoland/deno · error · anyhow::Error

Invalid file path

Error message

Invalid file path: {}

What it means

`deno transpile` converts each input path into a file:// ModuleSpecifier before parsing (cli/tools/transpile.rs:93-96). Url::from_file_path only accepts absolute, well-formed paths, so this guard fires when the cwd-joined path still cannot form a valid absolute file URL. It is a defensive check — ordinary relative or absolute .ts/.tsx inputs never trip it.

Solutions

  1. Pass a plain relative or absolute TypeScript path: deno transpile src/mod.ts.
  2. Inspect the failing argument (shown in the message) for stray quotes, spaces, or empty strings leaking in from a script.
  3. If it reproduces with a normal-looking path, capture the exact command line and report upstream — this branch should be unreachable for absolute paths.

Example fix

# before — argument polluted by script interpolation
$ deno transpile "${SRC_DIR}/mod.ts"   # SRC_DIR empty -> /mod.ts oddity or ""
error: Invalid file path: ...

# after — validate before invoking
$ test -n "$SRC_DIR" && deno transpile "$SRC_DIR/mod.ts"
Defensive patterns

Strategy: validation

Validate before calling

# Sanity-check every argument is a non-empty, absolute-or-cwd-relative .ts/.tsx file
for f in "$@"; do
  [ -n "$f" ] && [ -f "$f" ] || { echo "skipping invalid path: '$f'"; continue; }
done
deno transpile "$@"

Prevention

When it happens

Trigger: A transpile argument that degenerates into a non-absolute or malformed path (empty argument, a path composed only of `..` segments resolving above a relative cwd, or OS-specific invalid path forms).

Common situations: Programmatic invocation of deno transpile with unvalidated file lists; scripts passing glob results that include odd entries; embedding the CLI with an unusual working directory.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/138eca8d1ac3dd18. Report an issue: GitHub.

Appendix: source

Thrown at cli/tools/transpile.rs:95

  // Collect file paths and specifiers
  let mut file_entries = Vec::new();
  for file_path_str in files {
    let file_path = cwd.join(file_path_str);

    let media_type = MediaType::from_path(&file_path);
    if !media_type.is_emittable() {
      log::warn!(
        "{} Skipping {} (not a TypeScript/JSX/TSX file)",
        colors::yellow("Warning"),
        file_path.display()
      );
      continue;
    }

    let specifier =
      ModuleSpecifier::from_file_path(&file_path).map_err(|_| {
        anyhow::anyhow!("Invalid file path: {}", file_path.display())
      })?;

    file_entries.push((file_path, specifier, media_type));
  }

  if file_entries.is_empty() {
    anyhow::bail!(
      "No emittable files found. Only TypeScript/JSX/TSX files can be transpiled."
    );
  }

  // Transpile each file (TS -> JS)
  for (file_path, specifier, media_type) in &file_entries {
    let source_bytes = sys
      .fs_read(file_path)
      .with_context(|| format!("Failed to read {}", file_path.display()))?;
    let source_code = String::from_utf8(source_bytes.into_owned())
      .with_context(|| format!("{} is not valid UTF-8", file_path.display()))?;

View on GitHub (pinned to 9ad36f7a2c)