{"record":{"id":"0fea7a367c13961d","repo":"denoland/deno","slug":"redirects-should-be-resolved","errorCode":null,"errorMessage":"Redirects should be resolved","messagePattern":"Redirects should be resolved","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/eszip/v1.rs","lineNumber":87,"sourceCode":"          return Some(module);\n        }\n      }\n    }\n  }\n\n  pub fn get_import_map(&self, _specifier: &str) -> Option<Module> {\n    // V1 never contains an import map in it. This method exists to make it\n    // consistent with V2's interface.\n    None\n  }\n\n  /// Get source code of the module.\n  pub(crate) fn get_module_source(&self, specifier: &str) -> Option<Arc<[u8]>> {\n    let specifier = &Url::parse(specifier).ok()?;\n    let modules = self.modules.lock().unwrap();\n    let module = modules.get(specifier).unwrap();\n    match module {\n      ModuleInfo::Redirect(_) => panic!(\"Redirects should be resolved\"),\n      ModuleInfo::Source(module) => {\n        let source = module.transpiled.as_ref().unwrap_or(&module.source);\n        Some(source.clone().into())\n      }\n    }\n  }\n\n  /// Removes the module from the modules map and returns the source code.\n  pub(crate) fn take(&self, specifier: &str) -> Option<Arc<[u8]>> {\n    let specifier = &Url::parse(specifier).ok()?;\n    let mut modules = self.modules.lock().unwrap();\n    // Note: we don't have a need to preserve the module in the map for v1, so we can\n    // remove the module from the map. In v2, we need to preserve the module in the map\n    // to be able to get source map for the module.\n    let module = modules.remove(specifier)?;\n    match module {\n      ModuleInfo::Redirect(_) => panic!(\"Redirects should be resolved\"),\n      ModuleInfo::Source(module_source) => {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/libs/eszip/v1.rs#L69-L105","documentation":"EszipV1 is the legacy JSON-graph eszip format: module entries are either Redirect(target) or Source. The crate invariant is that redirects are resolved by navigation (EszipV1::get_module walks the redirect chain, v1.rs:46) before any source is requested, so get_module_source treats a ModuleInfo::Redirect lookup as an impossible state and panics. Hitting it means source was requested for the original (redirecting) specifier instead of the resolved target, or the archive's redirects were never resolved.","triggerScenarios":"Requesting module source with the pre-redirect specifier instead of the resolved one returned by get_module; a hand-edited or corrupt v1 eszip where the redirect-substitution step never happened; custom tooling reading the v1 JSON graph directly and bypassing navigation.","commonSituations":"Consuming very old `deno compile` artifacts (v1 era) with custom loaders; internal code paths changed by version skew; hand-built v1 archives assembled from a module map that still contains redirect entries.","solutions":["Always obtain modules via Eszip::parse(...).get_module(specifier) and use the returned Module's source()/take_source(), which operate on the resolved target","Re-compile the program with a current Deno to produce an eszip v2 archive instead of consuming v1","If you must handle v1 manually, walk ModuleInfo::Redirect chains to the terminal Source entry before touching sources","Validate the archive (EszipV1::parse round-trip plus get_module on every specifier) before loading it"],"exampleFix":"// before: source requested for the redirecting specifier\nlet spec = \"https://example.com/legacy.ts\"; // maps to ModuleInfo::Redirect\n// internal get_module_source(spec) -> panic!(\"Redirects should be resolved\")\n\n// after: get_module() follows redirects and binds to the resolved target\nlet module = eszip.get_module(spec).expect(\"resolves redirect chain\");\nlet source = module.source().await;","handlingStrategy":"validation","validationCode":"// Resolve through the public API before any source access.\nlet module = eszip.get_module(specifier)?; // follows redirects; None on missing/cycle\nlet source = module.source().await;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never feed raw specifiers to source access; use the Module returned by get_module","Use module.specifier (resolved) for any subsequent lookups","Prefer re-compiling artifacts to eszip v2 over maintaining v1 handling","Validate v1 archives by enumerating specifiers and get_module-ing each before loading"],"tags":["eszip","deno-compile","redirect","legacy-format","panic"],"backgroundTag":"eszip-redirect-resolution","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}