denoland/deno · error
Entry point must be a file
Error message
Entry point must be a file: {} What it means
After bundling with declaration (.d.ts) emission, Deno converts each entrypoint specifier to a local file path to locate and roll up the emitted declarations. If an entrypoint is not a `file://` URL (e.g. an `https://` remote entry), the conversion fails and declaration rollup aborts.
Solutions
- Vendor or download the remote module and pass a local file path as the entrypoint
- Keep entrypoints local — move the remote module behind a thin local wrapper module and use that as the entry
Example fix
# before deno bundle https://example.com/app.ts # after # vendor first, then bundle the local entry deno vendor https://example.com/app.ts deno bundle ./app.ts
Defensive patterns
Strategy: type-guard
Type guard
// Guard: only local file entries may be used as bundle entrypoints
function isLocalFileEntry(specifier: string): boolean {
try {
return new URL(specifier).protocol === "file:";
} catch {
return true; // bare relative paths resolve to files
}
}
const safe = entries.every(isLocalFileEntry); Prevention
- Vendor remote modules before bundling them as entries
- Keep bundle entrypoints as local files; remote imports are fine
When it happens
Trigger: Bundling with type emission enabled where an entrypoint specifier is a remote URL (e.g. `deno bundle https://example.com/mod.ts`) or any non-file specifier; imports may stay remote, but the entry itself must be local.
Common situations: Bundling a remote module straight from a URL instead of vendoring it first; alias/redirect entries that resolve to non-file URLs.
Related errors
- No declaration file emitted for entry point
- Cannot generate declarations for files with different…
- Type checking failed
- An executable name was not provided. One could not be…
- could not resolve the native TypeScript compiler; download
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/bc40810bbbe1646b.
Report an issue: GitHub.
Appendix: source
Thrown at cli/tools/bundle/mod.rs:492
// Index emitted .d.ts files by their original source specifier
// TSC emits keys like "file:///path/to/file.d.ts" - map them back to source paths
let mut dts_by_source: std::collections::HashMap<String, String> =
std::collections::HashMap::new();
for (file_name, content) in &result.emitted_files {
// Map "file:///path/to/mod.d.ts" -> normalized source path
if let Ok(specifier) = Url::parse(file_name)
&& let Ok(file_path) = specifier.to_file_path()
{
let source_path = file_path.to_string_lossy().to_string();
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.View on GitHub (pinned to 9ad36f7a2c)