{"record":{"id":"bc40810bbbe1646b","repo":"denoland/deno","slug":"entry-point-must-be-a-file","errorCode":null,"errorMessage":"Entry point must be a file: {}","messagePattern":"Entry point must be a file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/tools/bundle/mod.rs","lineNumber":492,"sourceCode":"\n  // Index emitted .d.ts files by their original source specifier\n  // TSC emits keys like \"file:///path/to/file.d.ts\" - map them back to source paths\n  let mut dts_by_source: std::collections::HashMap<String, String> =\n    std::collections::HashMap::new();\n  for (file_name, content) in &result.emitted_files {\n    // Map \"file:///path/to/mod.d.ts\" -> normalized source path\n    if let Ok(specifier) = Url::parse(file_name)\n      && let Ok(file_path) = specifier.to_file_path()\n    {\n      let source_path = file_path.to_string_lossy().to_string();\n      dts_by_source.insert(source_path, content.clone());\n    }\n  }\n\n  // For each entry point, produce a single rolled-up .d.ts\n  for entry_specifier in &entrypoint_specifiers {\n    let entry_path = entry_specifier.to_file_path().map_err(|_| {\n      deno_core::anyhow::anyhow!(\n        \"Entry point must be a file: {}\",\n        entry_specifier\n      )\n    })?;\n\n    // Find the .d.ts for this entry point\n    let dts_path = to_dts_path(&entry_path);\n    let entry_dts = dts_by_source\n      .get(&dts_path.to_string_lossy().to_string())\n      .ok_or_else(|| {\n        deno_core::anyhow::anyhow!(\n          \"No declaration file emitted for entry point: {}\",\n          entry_specifier\n        )\n      })?;\n\n    // Flatten: resolve all `export ... from \"...\"` re-exports by inlining\n    // the referenced declarations from other .d.ts files.","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/cli/tools/bundle/mod.rs#L474-L510","documentation":"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.","triggerScenarios":"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.","commonSituations":"Bundling a remote module straight from a URL instead of vendoring it first; alias/redirect entries that resolve to non-file URLs.","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"],"exampleFix":"# before\ndeno bundle https://example.com/app.ts\n\n# after\n# vendor first, then bundle the local entry\ndeno vendor https://example.com/app.ts\ndeno bundle ./app.ts","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Guard: only local file entries may be used as bundle entrypoints\nfunction isLocalFileEntry(specifier: string): boolean {\n  try {\n    return new URL(specifier).protocol === \"file:\";\n  } catch {\n    return true; // bare relative paths resolve to files\n  }\n}\nconst safe = entries.every(isLocalFileEntry);","tryCatchPattern":null,"preventionTips":["Vendor remote modules before bundling them as entries","Keep bundle entrypoints as local files; remote imports are fine"],"tags":["bundle","typescript","declarations","remote-module","entrypoint"],"backgroundTag":"remote-entrypoint-unsupported","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}