bevyengine/bevy · critical
Error when initializing schedule {:?}: {}
Error message
Error when initializing schedule {:?}: {} What it means
Schedule::run initializes the schedule before executing it; if building the executable schedule fails (ordering cycles, self-loops, ambiguous SystemTypeSet ordering, other build errors), run() panics with this wrapper message. The text after the colon embeds the underlying ScheduleBuildError rendered against the graph and world, naming the offending nodes/edges. It fires on the first run of the schedule, typically the first frame.
Source
Thrown at crates/bevy_ecs/src/schedule/schedule.rs:575
}
/// Set whether the schedule applies deferred system buffers on final time or not. This is a catch-all
/// in case a system uses commands but was not explicitly ordered before an instance of
/// [`ApplyDeferred`]. By default this
/// setting is true, but may be disabled if needed.
pub fn set_apply_final_deferred(&mut self, apply_final_deferred: bool) -> &mut Self {
self.executor.set_apply_final_deferred(apply_final_deferred);
self
}
/// Runs all systems in this schedule on the `world`, using its current execution strategy.
pub fn run(&mut self, world: &mut World) {
#[cfg(feature = "trace")]
let _span = info_span!("schedule", name = ?self.label).entered();
world.check_change_ticks();
self.initialize(world).unwrap_or_else(|e| {
panic!(
"Error when initializing schedule {:?}: {}",
self.label,
e.to_string(self.graph(), world)
)
});
let error_handler = world.fallback_error_handler();
#[cfg(not(feature = "bevy_debug_stepping"))]
self.executor
.run(&mut self.executable, world, None, error_handler);
#[cfg(feature = "bevy_debug_stepping")]
{
let skip_systems = match world.get_resource_mut::<Stepping>() {
None => None,
Some(mut stepping) => stepping.skipped_systems(self),
};View on GitHub (pinned to 396ca72708)
Solutions
- Read the embedded detail after the colon - it identifies the exact nodes and constraint at fault; fix that underlying build error.
- Reproduce as a failing test: call app.update() once right after configuring systems so CI catches it before runtime.
- If you need the error instead of a panic, call schedule.initialize(&mut world) yourself and handle the Result before calling run().
Example fix
// before
schedule.run(&mut world); // panics on invalid graph
// after
if let Err(e) = schedule.initialize(&mut world) {
log::error!("bad schedule: {}", e.to_string(schedule.graph(), world));
return;
}
schedule.run(&mut world); Defensive patterns
Strategy: try-catch
Validate before calling
// Fail fast in a test instead of frame 1
#[test]
fn app_boots() {
let mut app = App::new();
app.add_plugins(DefaultPlugins);
app.update();
} Try / catch
if let Err(e) = schedule.initialize(&mut world) {
log::error!("schedule init failed: {}", e.to_string(schedule.graph(), world));
return; // skip running instead of letting run() panic
}
schedule.run(&mut world); Prevention
- Run one app.update() in CI for every schedule composition you ship.
- Centralize schedule configuration so constraints are auditable in one module.
- Treat any new ordering constraint as requiring a smoke test.
When it happens
Trigger: Any ScheduleBuildError surfacing through Schedule::run: a cycle or self-loop introduced by new ordering constraints, ordering against a duplicated system type, or graph inconsistencies added since the last successful run.
Common situations: App panics on frame 1 after adding a plugin or ordering constraint; systems/sets configured differently between test and app so a constraint only loops in one of them; large refactors of schedule configuration.
Related errors
- Uninitialized
- System with key {:?} does not exist in the schedule
- System set with key {:?} does not exist in the schedule
- executable schedule has not been built
- BuilderSystem {} was not initialized before calling run_unsa
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/9e8ef7bae2ad9bd3.
Report an issue: GitHub.