denoland/deno · critical
Attempted to read snapshot data out of range: {id} (of {})
Error message
Attempted to read snapshot data out of range: {id} (of {}) What it means
When a JsRuntime boots from a startup snapshot, load_snapshotted_data_from_snapshot rebuilds a SnapshotLoadDataStore, and extensions pull their snapshotted state out of it by index (SnapshotDataId, jsruntime.rs:1058+). get() panics "out of range" when an extension requests an id at or beyond the number of entries the snapshot actually stored. That means the extension/state layout at runtime no longer matches the layout that existed when the snapshot was created.
Source
Thrown at libs/core/runtime/snapshot.rs:73
data.into_boxed_slice()
}
#[derive(Default)]
pub struct SnapshotLoadDataStore {
data: Vec<Option<v8::Global<v8::Data>>>,
}
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)
}
}
View on GitHub (pinned to f7822238ca)
Solutions
- Regenerate the startup snapshot so the stored state list matches the runtime's extension layout
- Make the extension vector (set and order) identical between create_snapshot options and RuntimeOptions at boot
- Wire create_snapshot's returned files into cargo:rerun-if-changed so the snapshot rebuilds whenever extension inputs change
- Pin deno_core and all extension crates to the same versions on both sides
Example fix
// before: snapshot built with [ext_a, ext_b], runtime boots [ext_a, ext_c, ext_b]
let rt = JsRuntime::new(RuntimeOptions {
extensions: vec![ext_a(), ext_c(), ext_b()],
startup_snapshot: Some(&SNAP),
..Default::default()
});
// after: same vector (order included) in build.rs and at boot
// build.rs: create_snapshot(CreateSnapshotOptions { extensions: vec![ext_a(), ext_c(), ext_b()], .. })
let rt = JsRuntime::new(RuntimeOptions {
extensions: vec![ext_a(), ext_c(), ext_b()],
startup_snapshot: Some(&REBUILT_SNAP),
..Default::default()
}); Defensive patterns
Strategy: validation
Validate before calling
// Stamp the extension layout into the snapshot artifact and check it before boot.
const SNAPSHOT_LAYOUT: &str = "ext-a:1,ext-c:2,ext-b:3"; // generated in build.rs
fn assert_layout(snapshot_tag: &str) {
assert_eq!(snapshot_tag, SNAPSHOT_LAYOUT,
"extension layout changed; regenerate the startup snapshot");
} Prevention
- Keep the extension vector (names and order) identical in create_snapshot and RuntimeOptions
- Regenerate the snapshot whenever an extension with snapshot state is added, removed, or reordered
- Treat snapshot and binary as one unit in CI: build, store, and deploy them together
- Disable CI caching of snapshot artifacts across dependency bumps
When it happens
Trigger: Adding, removing, or reordering extensions that carry snapshot state between create_snapshot and runtime startup; loading a startup snapshot built by a different deno_core/deno_runtime version with a different state layout; concatenating or hand-editing snapshot blobs.
Common situations: Bumping deno_core or an extension crate version without regenerating the startup snapshot; feature flags that conditionally include an extension in the runtime but not in the snapshot build (or vice versa); CI caching a stale snapshot artifact.
Related errors
- Attempted to read the snapshot data at index {id} twice
- Invalid data type at index {id}, expected '{}'
- {path} exists
- unable to convert
- Failed to initialize a JsRuntime: {}
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/d608ee31f86de656.
Report an issue: GitHub.