denoland/deno · critical

Attempted to read the snapshot data at index {id} twice

Error message

Attempted to read the snapshot data at index {id} twice

What it means

SnapshotLoadDataStore::get moves each snapshotted value out of its slot with Option::take, so a given SnapshotDataId can be consumed exactly once. The panic "read the snapshot data at index {id} twice" fires when the same index is requested again after it was already taken. This is a programming invariant inside extension state deserialization: one state entry must map to exactly one consumer during runtime boot.

Source

Thrown at libs/core/runtime/snapshot.rs:79

}

impl SnapshotLoadDataStore {
  pub fn get<'s, 'i, T>(
    &mut self,
    scope: &mut v8::PinScope<'s, 'i>,
    id: SnapshotDataId,
  ) -> v8::Global<T>
  where
    v8::Local<'s, T>: TryFrom<v8::Local<'s, v8::Data>>,
  {
    let Some(data) = self.data.get_mut(id as usize) else {
      panic!(
        "Attempted to read snapshot data out of range: {id} (of {})",
        self.data.len()
      );
    };
    let Some(data) = data.take() else {
      panic!("Attempted to read the snapshot data at index {id} twice");
    };
    let local = v8::Local::new(scope, data);
    let local = v8::Local::<T>::try_from(local).unwrap_or_else(|_| {
      panic!(
        "Invalid data type at index {id}, expected '{}'",
        std::any::type_name::<T>()
      )
    });
    v8::Global::new(scope, local)
  }
}

#[derive(Default)]
pub struct SnapshotStoreDataStore {
  data: Vec<v8::Global<v8::Data>>,
}

impl SnapshotStoreDataStore {

View on GitHub (pinned to f7822238ca)

Solutions

  1. Ensure each snapshot state entry is loaded exactly once per JsRuntime boot; do not re-use the boot SnapshotLoadDataStore for extra realms
  2. Audit extensions for duplicate state registrations sharing one id
  3. Regenerate the snapshot after changing any state callback layout
  4. Align deno_core/extension versions between snapshot creation and consumption
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: An extension's state deserialization callback running twice against the same store (e.g. invoked for an extra realm or a second runtime sharing the store); two extensions (or a duplicated state registration) requesting the same SnapshotDataId; custom embeddings that re-run snapshot state loading manually after JsRuntime init already consumed it.

Common situations: Embeddings that create additional realms and reuse the boot-time SnapshotLoadDataStore instead of fresh per-realm state; refactors that accidentally register the same snapshot state type/id twice; version skew changing how many state entries an extension consumes.

Related errors


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