bevyengine/bevy · critical
System with key {:?} does not exist in the schedule
Error message
System with key {:?} does not exist in the schedule What it means
Panics when the schedule's system container (Systems, a slot map) is indexed with a SystemKey that is not live: systems[key] via the Index impl. Keys are slot-map handles scoped to one container; a removed system frees its key, and keys from another schedule were never valid. Almost always indicates stale or foreign keys, not a Bevy bug.
Source
Thrown at crates/bevy_ecs/src/schedule/node.rs:649
// for example 2 systems with `Query<EntityMut>`
conflicting_systems.push((a, b, Box::new([])));
}
}
}
}
}
ConflictingSystems(conflicting_systems)
}
}
impl Index<SystemKey> for Systems {
type Output = SystemWithAccess;
#[track_caller]
fn index(&self, key: SystemKey) -> &Self::Output {
self.get(key)
.unwrap_or_else(|| panic!("System with key {:?} does not exist in the schedule", key))
}
}
impl IndexMut<SystemKey> for Systems {
#[track_caller]
fn index_mut(&mut self, key: SystemKey) -> &mut Self::Output {
self.get_mut(key)
.unwrap_or_else(|| panic!("System with key {:?} does not exist in the schedule", key))
}
}
/// Pairs of systems that conflict with each other along with the components
/// they conflict on, which prevents them from running in parallel. If the
/// component list is empty, the systems conflict on [`World`] access in general
/// (e.g. one of them is exclusive, or both systems have `Query<EntityMut>`).
#[derive(Clone, Debug, Default)]
pub struct ConflictingSystems(pub Vec<(SystemKey, SystemKey, Box<[ComponentId]>)>);
View on GitHub (pinned to 396ca72708)
Solutions
- Replace indexing with systems.get(key) and handle the None case explicitly.
- Re-fetch keys from the owning schedule after any modification/rebuild instead of caching them.
- Verify the key was produced by the same schedule instance you are indexing - cross-schedule lookups should go by name or type, not key.
Example fix
// before
let system = systems[key]; // panics on stale/foreign key
// after
let Some(system) = systems.get(key) else {
// key no longer valid here; refresh keys from the schedule
return;
}; Defensive patterns
Strategy: validation
Validate before calling
if systems.get(key).is_some() {
let system = &systems[key]; // now known-valid
} else {
// key is stale: re-fetch from the owning schedule
} Type guard
fn system_key_is_live(systems: &Systems, key: SystemKey) -> bool {
systems.get(key).is_some()
} Prevention
- Treat SystemKey as schedule-local and non-durable: never cache across rebuilds.
- Prefer .get()/get_mut() over the [] operators for key lookups.
- Cross-reference systems by name or type, not by key, when data crosses schedule boundaries.
When it happens
Trigger: Indexing with a key captured from a different Schedule; holding a SystemKey across a schedule change that removed the system; editor/stepping/debug tooling or custom executors re-using keys cached before a schedule rebuild.
Common situations: Editor or stepping UIs that cache SystemKeys between frames while systems are added/removed; plugins storing keys in resources that outlive the schedule they came from; refactors that mix keys from two schedules.
Related errors
- System set with key {:?} does not exist in the schedule
- Error when initializing schedule {:?}: {}
- Cannot call `ReflectComponent::reflect_mut` on component {na
- Cannot call `ReflectComponent::reflect_unchecked_mut` on com
- Resource entity {} of {} has been despawned, when it's not s
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/4cd6283ca88eb13d.
Report an issue: GitHub.