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

  1. Replace indexing with systems.get(key) and handle the None case explicitly.
  2. Re-fetch keys from the owning schedule after any modification/rebuild instead of caching them.
  3. 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

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


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/4cd6283ca88eb13d. Report an issue: GitHub.