denoland/deno · error
No declaration file emitted for entry point: {}
Error message
No declaration file emitted for entry point: {} What it means
After tsc emits declarations, the emitted files are indexed by source path and each entrypoint looks up its expected .d.ts (to_dts_path, cli/tools/bundle/mod.rs:498-507). This error means no emitted declaration matched the entry - most commonly because the entrypoint is JavaScript (tsc emits .d.ts for TS sources under these settings) or produced no emitted output at all.
Source
Thrown at cli/tools/bundle/mod.rs:503
dts_by_source.insert(source_path, content.clone());
}
}
// For each entry point, produce a single rolled-up .d.ts
for entry_specifier in &entrypoint_specifiers {
let entry_path = entry_specifier.to_file_path().map_err(|_| {
deno_core::anyhow::anyhow!(
"Entry point must be a file: {}",
entry_specifier
)
})?;
// Find the .d.ts for this entry point
let dts_path = to_dts_path(&entry_path);
let entry_dts = dts_by_source
.get(&dts_path.to_string_lossy().to_string())
.ok_or_else(|| {
deno_core::anyhow::anyhow!(
"No declaration file emitted for entry point: {}",
entry_specifier
)
})?;
// Flatten: resolve all `export ... from "..."` re-exports by inlining
// the referenced declarations from other .d.ts files.
let flattened =
flatten_declarations(entry_dts, &entry_path, &dts_by_source);
// Determine output path for the rolled-up .d.ts
let dts_output_path = if let Some(ref output) = bundle_flags.output_path {
let js_path = init_cwd.join(output);
to_dts_path(&js_path)
} else if let Some(ref outdir) = bundle_flags.output_dir {
let outdir = PathBuf::from(outdir);
let stem = entry_path.file_stem().unwrap_or_default();
outdir.join(format!("{}.d.ts", stem.to_string_lossy()))View on GitHub (pinned to 89f33cbef2)
Solutions
- Make the entrypoint a TypeScript module (.ts/.mts/.tsx) - declarations are emitted for TS sources
- If the entry only re-exports types, convert it to TS so tsc emits a .d.ts for it
- Verify with 'deno check <entry>' that the entry itself type-checks and has emittable contents
- If a plain TS entry still hits this on current Deno, report it - the emitted-file indexing may have a path-mapping bug
Example fix
// before: JS entry - no .d.ts emitted for it
// app.js: export function add(a, b) { return a + b; }
// run: deno bundle --declaration app.js --outdir dist -> error
// after: TS entry
// app.ts: export function add(a: number, b: number): number { return a + b; }
// run: deno bundle --declaration app.ts --outdir dist Defensive patterns
Strategy: validation
Validate before calling
# Verify the entry is a TypeScript source before --declaration bundling case "$1" in *.ts|*.mts|*.cts|*.tsx) ;; *) echo 'declaration emission requires a TS entrypoint'; exit 2;; esac deno bundle --declaration "$1" --outdir dist
Type guard
const TS_EXTENSIONS = ['.ts', '.mts', '.cts', '.tsx'] as const;
function isTsEntrypoint(path: string): boolean {
return TS_EXTENSIONS.some((ext) => path.toLowerCase().endsWith(ext));
} Prevention
- Convert JS entries to TS when declaration artifacts are needed
- Check that entries export runtime values (type-only entries may emit nothing)
- Smoke-test 'deno bundle --declaration' in CI so entry drift is caught early
When it happens
Trigger: 'deno bundle --declaration app.js ...' where the entry is .js/.mjs (no declaration emitted for it); a TS entry that is type-only and yields no emitted .d.ts; emitted keys failing to map back through the file:// path index (unusual path casing/symlinks).
Common situations: Projects with a JS entry adding --declaration late; mixed JS/TS codebases bundling the JS entry; entries that only re-export types.
Related errors
- Type checking failed when generating declarations:\n{}
- Entry point must be a file: {}
- The bench function must have a name
- ${prefix}Linter plugin name must be a string
- Invalid cron schedule: start=${start}, end=${end}, every=${e
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/2d0da6d04b08fd43.
Report an issue: GitHub.