{"record":{"id":"a757c542b8706fcf","repo":"denoland/deno","slug":"attempted-to-read-the-snapshot-data-at-index-id","errorCode":null,"errorMessage":"Attempted to read the snapshot data at index {id} twice","messagePattern":"Attempted to read the snapshot data at index (.+?) twice","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"libs/core/runtime/snapshot.rs","lineNumber":79,"sourceCode":"}\n\nimpl SnapshotLoadDataStore {\n  pub fn get<'s, 'i, T>(\n    &mut self,\n    scope: &mut v8::PinScope<'s, 'i>,\n    id: SnapshotDataId,\n  ) -> v8::Global<T>\n  where\n    v8::Local<'s, T>: TryFrom<v8::Local<'s, v8::Data>>,\n  {\n    let Some(data) = self.data.get_mut(id as usize) else {\n      panic!(\n        \"Attempted to read snapshot data out of range: {id} (of {})\",\n        self.data.len()\n      );\n    };\n    let Some(data) = data.take() else {\n      panic!(\"Attempted to read the snapshot data at index {id} twice\");\n    };\n    let local = v8::Local::new(scope, data);\n    let local = v8::Local::<T>::try_from(local).unwrap_or_else(|_| {\n      panic!(\n        \"Invalid data type at index {id}, expected '{}'\",\n        std::any::type_name::<T>()\n      )\n    });\n    v8::Global::new(scope, local)\n  }\n}\n\n#[derive(Default)]\npub struct SnapshotStoreDataStore {\n  data: Vec<v8::Global<v8::Data>>,\n}\n\nimpl SnapshotStoreDataStore {","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/libs/core/runtime/snapshot.rs#L61-L97","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure each snapshot state entry is loaded exactly once per JsRuntime boot; do not re-use the boot SnapshotLoadDataStore for extra realms","Audit extensions for duplicate state registrations sharing one id","Regenerate the snapshot after changing any state callback layout","Align deno_core/extension versions between snapshot creation and consumption"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Consume each snapshot state entry exactly once per runtime boot","Do not reuse the boot-time SnapshotLoadDataStore when creating extra realms; use fresh per-realm state","Audit extensions for duplicate registrations of the same snapshot state id","Regenerate the snapshot after any change to state callbacks"],"tags":["deno-core","snapshot","extensions","double-consumption","panic"],"backgroundTag":"snapshot-data-mismatch","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}