{"record":{"id":"06eef6ac8201183e","repo":"denoland/deno","slug":"invalid-declaration-file-path","errorCode":null,"errorMessage":"Invalid declaration file path","messagePattern":"Invalid declaration file path","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"cli/tools/transpile.rs","lineNumber":373,"sourceCode":"  } else {\n    PathBuf::from(tsc_file_name)\n  };\n\n  if let Some(outdir) = output_dir {\n    // --outdir: preserve relative directory structure\n    let outdir = cwd.join(outdir);\n    let relative = path.strip_prefix(cwd).map_err(|_| {\n      anyhow::anyhow!(\n        \"Declaration file {} is not under the current directory\",\n        path.display()\n      )\n    })?;\n    Ok(outdir.join(relative))\n  } else if let Some(base_dir) = output_base_dir {\n    // -o: place .d.ts next to the output file\n    let file_name = path\n      .file_name()\n      .ok_or_else(|| anyhow::anyhow!(\"Invalid declaration file path\"))?;\n    Ok(base_dir.join(file_name))\n  } else {\n    // No output specified: place next to source file\n    Ok(path)\n  }\n}\n\n/// SWC's code generator always writes a single space after a block\n/// comment's closing `*/`, regardless of whether the original source had a\n/// newline. For multi-line block comments (typically JSDoc) this collapses\n/// the comment onto the same line as the following statement. This function\n/// walks the emitted source and replaces that single space with a newline\n/// (plus the comment's own leading indentation) when the preceding block\n/// comment spans multiple lines.\nfn restore_block_comment_newlines(input: &str) -> String {\n  let bytes = input.as_bytes();\n  let n = bytes.len();\n  let mut out: Vec<u8> = Vec::with_capacity(n);","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/cli/tools/transpile.rs#L355-L391","documentation":"When placing a declaration next to a `--output` file, the code needs the declaration path's final component via `path.file_name()`; for degenerate paths (a filesystem root, or a path ending in `..`) it returns None and this guard fires. It is a defensive check against malformed tsc-reported output paths.","triggerScenarios":"A declaration file name reported by the native compiler that has no final component while using -o. Practically unreachable through normal CLI use.","commonSituations":"Not user-triggered in practice; would indicate corrupt/abnormal tsc output or a path-manipulation bug in deno itself.","solutions":["Re-run without -o (default placement next to sources) to see whether the malformed path reproduces","If it reproduces, capture the command, inputs, and printed path and report an issue to the deno repository"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"# shell: retry without -o placement if the defensive guard trips\nif ! deno transpile mod.ts --declaration -o out/mod.js 2>err.log; then\n  grep -q \"Invalid declaration file path\" err.log && deno transpile mod.ts --declaration  # default placement next to source\nfi","preventionTips":["Prefer default (next-to-source) declaration placement; use -o only when the path is known sane","Keep toolchain versions pinned so tsc output paths stay predictable","Report reproductions upstream — this guard indicates abnormal compiler output"],"tags":["cli","transpile","declarations","paths","internal"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}