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

  1. Make the entrypoint a TypeScript module (.ts/.mts/.tsx) - declarations are emitted for TS sources
  2. If the entry only re-exports types, convert it to TS so tsc emits a .d.ts for it
  3. Verify with 'deno check <entry>' that the entry itself type-checks and has emittable contents
  4. 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

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


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/2d0da6d04b08fd43. Report an issue: GitHub.