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

  1. Fetch modules only through Eszip::get_module/get_import_map and call source() on the returned Module
  2. Re-compile or re-package the artifact with the current eszip version
  3. Verify integrity before loading: parse succeeds, every needed specifier resolves via get_module, specifiers() round-trips
  4. 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

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


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/f078ea598321b737. Report an issue: GitHub.