denoland/deno · error
redirects are already resolved
Error message
redirects are already resolved
What it means
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.
Source
Thrown at libs/eszip/v2.rs:103
Redirect = 1,
NpmSpecifier = 2,
}
#[derive(Debug, Default, Clone)]
pub struct EszipV2Modules(Arc<Mutex<LinkedHashMap<String, EszipV2Module>>>);
impl EszipV2Modules {
pub(crate) async fn get_module_source(
&self,
specifier: &str,
) -> Option<Arc<[u8]>> {
poll_fn(|cx| {
let mut modules = self.0.lock().unwrap();
let module = modules.get_mut(specifier).unwrap();
let slot = match module {
EszipV2Module::Module { source, .. } => source,
EszipV2Module::Redirect { .. } => {
panic!("redirects are already resolved")
}
};
match slot {
EszipV2SourceSlot::Pending { wakers, .. } => {
wakers.push(cx.waker().clone());
Poll::Pending
}
EszipV2SourceSlot::Ready(bytes) => Poll::Ready(Some(bytes.clone())),
EszipV2SourceSlot::Taken => Poll::Ready(None),
}
})
.await
}
pub(crate) async fn take_module_source(
&self,
specifier: &str,
) -> Option<Arc<[u8]>> {View on GitHub (pinned to 9ad36f7a2c)
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
Example fix
// before: holding the pre-redirect specifier
let spec = "https://example.com/pkg/mod.ts"; // Redirect entry in the archive
// internal get_module_source(spec) -> panic!("redirects are already resolved")
// after: resolve first, then use the resolved module
let module = eszip.get_module(spec).unwrap();
let source = module.source().await; Defensive patterns
Strategy: validation
Validate before calling
// Check resolution up front: get_module returns None for missing targets or cycles.
match eszip.get_module(specifier) {
Some(module) => { let src = module.source().await; /* ... */ }
None => /* handle unresolved/missing module */,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Custom loaders built on eszip internals rather than the public Module API; eszip archives produced by mismatched writer versions; hand-modified compiled artifacts.
Related errors
- Redirects should be resolved
- invalid module type
- Import map not found in eszip: {}
- Cannot read url: request closed
- Invalid redirect status code: ${status}
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/f078ea598321b737.
Report an issue: GitHub.