denoland/deno · error · anyhow::Error
Invalid declaration file path
Error message
Invalid declaration file path
What it means
In `-o` (single output) mode the emitted declaration is written as base_dir + file_name (cli/tools/transpile.rs:369-374). Path::file_name() returns None only for degenerate paths that terminate in `..` or name the filesystem root, so this guard is practically unreachable through normal `deno transpile` usage — it exists to keep a malformed tsc-reported name from producing a bogus output path.
Solutions
- Re-run with explicit, concrete input file paths (no trailing .. segments or generated virtual paths).
- If it reproduces, record the exact deno transpile invocation and the tsconfig/deno.json in effect and report it upstream.
Defensive patterns
Strategy: validation
Prevention
- Give deno transpile concrete input filenames without trailing .. or virtual path segments.
- If you never see this error, ignore it — it guards a degenerate case unreachable in normal use.
When it happens
Trigger: A tsc-reported declaration specifier whose path normalizes to something ending in `..` (pathological tsconfig references or generated virtual file names).
Common situations: Not seen in normal use; would indicate a highly unusual compiler/emit configuration.
Related errors
- Declaration file is not under the current directory
- Input file is not under the current directory. Use --output…
- Invalid file path
- app bundle has no name
- Could not get parent of
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/06eef6ac8201183e.
Report an issue: GitHub.
Appendix: source
Thrown at cli/tools/transpile.rs:373
} else {
PathBuf::from(tsc_file_name)
};
if let Some(outdir) = output_dir {
// --outdir: preserve relative directory structure
let outdir = cwd.join(outdir);
let relative = path.strip_prefix(cwd).map_err(|_| {
anyhow::anyhow!(
"Declaration file {} is not under the current directory",
path.display()
)
})?;
Ok(outdir.join(relative))
} else if let Some(base_dir) = output_base_dir {
// -o: place .d.ts next to the output file
let file_name = path
.file_name()
.ok_or_else(|| anyhow::anyhow!("Invalid declaration file path"))?;
Ok(base_dir.join(file_name))
} else {
// No output specified: place next to source file
Ok(path)
}
}
/// SWC's code generator always writes a single space after a block
/// comment's closing `*/`, regardless of whether the original source had a
/// newline. For multi-line block comments (typically JSDoc) this collapses
/// the comment onto the same line as the following statement. This function
/// walks the emitted source and replaces that single space with a newline
/// (plus the comment's own leading indentation) when the preceding block
/// comment spans multiple lines.
fn restore_block_comment_newlines(input: &str) -> String {
let bytes = input.as_bytes();
let n = bytes.len();
let mut out: Vec<u8> = Vec::with_capacity(n);View on GitHub (pinned to 9ad36f7a2c)