{"record":{"id":"f078ea598321b737","repo":"denoland/deno","slug":"redirects-are-already-resolved","errorCode":null,"errorMessage":"redirects are already resolved","messagePattern":"redirects are already resolved","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/eszip/v2.rs","lineNumber":103,"sourceCode":"  Redirect = 1,\n  NpmSpecifier = 2,\n}\n\n#[derive(Debug, Default, Clone)]\npub struct EszipV2Modules(Arc<Mutex<LinkedHashMap<String, EszipV2Module>>>);\n\nimpl EszipV2Modules {\n  pub(crate) async fn get_module_source(\n    &self,\n    specifier: &str,\n  ) -> Option<Arc<[u8]>> {\n    poll_fn(|cx| {\n      let mut modules = self.0.lock().unwrap();\n      let module = modules.get_mut(specifier).unwrap();\n      let slot = match module {\n        EszipV2Module::Module { source, .. } => source,\n        EszipV2Module::Redirect { .. } => {\n          panic!(\"redirects are already resolved\")\n        }\n      };\n      match slot {\n        EszipV2SourceSlot::Pending { wakers, .. } => {\n          wakers.push(cx.waker().clone());\n          Poll::Pending\n        }\n        EszipV2SourceSlot::Ready(bytes) => Poll::Ready(Some(bytes.clone())),\n        EszipV2SourceSlot::Taken => Poll::Ready(None),\n      }\n    })\n    .await\n  }\n\n  pub(crate) async fn take_module_source(\n    &self,\n    specifier: &str,\n  ) -> Option<Arc<[u8]>> {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/libs/eszip/v2.rs#L85-L121","documentation":"In eszip v2, EszipV2Modules::get_module_source resolves a module's source slot and panics if the entry is EszipV2Module::Redirect. The public path (EszipV2::get_module -> lookup, v2.rs:1688) follows redirect chains to the terminal Module entry, so a Redirect should never be reached here. The panic therefore signals an unresolved specifier reaching the internals: a caller used the pre-redirect specifier directly, or the archive is malformed.","triggerScenarios":"Calling the crate-internal source accessor with the original specifier of a redirect entry instead of the resolved one; a corrupt v2 eszip where the redirect target entry is missing so navigation is bypassed; custom tooling reaching into the modules map instead of using get_module.","commonSituations":"Custom loaders built on eszip internals rather than the public Module API; eszip archives produced by mismatched writer versions; hand-modified compiled artifacts.","solutions":["Fetch modules only through Eszip::get_module/get_import_map and call source() on the returned Module","Re-compile or re-package the artifact with the current eszip version","Verify integrity before loading: parse succeeds, every needed specifier resolves via get_module, specifiers() round-trips","Avoid keeping references to pre-redirect specifiers after resolution; use module.specifier"],"exampleFix":"// before: holding the pre-redirect specifier\nlet spec = \"https://example.com/pkg/mod.ts\"; // Redirect entry in the archive\n// internal get_module_source(spec) -> panic!(\"redirects are already resolved\")\n\n// after: resolve first, then use the resolved module\nlet module = eszip.get_module(spec).unwrap();\nlet source = module.source().await;","handlingStrategy":"validation","validationCode":"// Check resolution up front: get_module returns None for missing targets or cycles.\nmatch eszip.get_module(specifier) {\n  Some(module) => { let src = module.source().await; /* ... */ }\n  None => /* handle unresolved/missing module */,\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always resolve via get_module/get_import_map; treat their internals as off-limits","Store resolved specifiers (module.specifier) rather than original URLs in loader caches","Validate archives by sweeping specifiers() with get_module before first use","Regenerate artifacts with the same eszip version that will read them"],"tags":["eszip","deno-compile","redirect","v2","panic"],"backgroundTag":"eszip-redirect-resolution","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}