bevyengine/bevy · error · ScheduleBuildError
Uninitialized
Uninitialized
Error message
Tried to run a schedule before all of its systems have been initialized.
What it means
`ScheduleBuildError::Uninitialized` is returned from the internal schedule-update step when the system/set stores are not fully initialized — in practice this means the schedule graph changed (systems or sets added/removed) and a previous `Schedule::initialize` did not complete, often because it failed on an earlier build error, leaving a half-built schedule. Initialization must run to completion before the executable schedule can be updated.
Source
Thrown at crates/bevy_ecs/src/schedule/error.rs:42
#[error("Failed to topologically sort the hierarchy of system sets: {0}")]
HierarchySort(DiGraphToposortError<NodeId>),
/// Tried to topologically sort the dependency graph.
#[error("Failed to topologically sort the dependency graph: {0}")]
DependencySort(DiGraphToposortError<NodeId>),
/// Tried to topologically sort the flattened dependency graph.
#[error("Failed to topologically sort the flattened dependency graph: {0}")]
FlatDependencySort(DiGraphToposortError<SystemKey>),
/// Tried to order a system (set) relative to a system set it belongs to.
#[error("`{:?}` and `{:?}` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.", .0.0, .0.1)]
CrossDependency(#[from] DagCrossDependencyError<NodeId>),
/// Tried to order system sets that share systems.
#[error("`{:?}` and `{:?}` have a `before`-`after` relationship (which may be transitive) but share systems.", .0.0, .0.1)]
SetsHaveOrderButIntersect(#[from] DagOverlappingGroupError<SystemSetKey>),
/// Tried to order a system (set) relative to all instances of some system function.
#[error(transparent)]
SystemTypeSetAmbiguity(#[from] SystemTypeSetAmbiguityError),
/// Tried to run a schedule before all of its systems have been initialized.
#[error("Tried to run a schedule before all of its systems have been initialized.")]
Uninitialized,
/// A warning that was elevated to an error.
#[error(transparent)]
Elevated(#[from] ScheduleBuildWarning),
}
/// Category of warnings encountered during [`Schedule::initialize`](crate::schedule::Schedule::initialize).
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum ScheduleBuildWarning {
/// The hierarchy of system sets contains redundant edges.
///
/// This warning is **enabled** by default, but can be disabled by setting
/// [`ScheduleBuildSettings::hierarchy_detection`] to [`LogLevel::Ignore`]
/// or upgraded to a [`ScheduleBuildError`] by setting it to [`LogLevel::Error`].
///
/// [`ScheduleBuildSettings::hierarchy_detection`]: crate::schedule::ScheduleBuildSettings::hierarchy_detection
/// [`LogLevel::Ignore`]: crate::schedule::LogLevel::IgnoreView on GitHub (pinned to 396ca72708)
Solutions
- Let the normal path rebuild the schedule: run `world.run_schedule(label)` or the app — `Schedule::initialize` is invoked automatically and rebuilds from the current graph
- When calling `schedule.initialize(world)` manually, handle the `Result` and fix the first reported build error so initialization completes instead of leaving partial state
- Avoid mutating a schedule (add_systems / remove_systems_in_set) while its build has failed or its systems are being iterated
Example fix
// before let _ = schedule.initialize(&mut world); // earlier error ignored, state half-built run_schedule_internals(&schedule); // ScheduleBuildError::Uninitialized // after schedule.initialize(&mut world)?; // propagate and fix the root build error first
Defensive patterns
Strategy: try-catch
Validate before calling
// Always propagate initialization errors instead of continuing with a half-built schedule schedule.initialize(&mut world)?; // ? propagates; fix the root build error before further ops
Try / catch
match schedule.initialize(&mut world) {
Err(ScheduleBuildError::Uninitialized) => {
// previous build failed partway: fix prior errors, then re-run initialize to completion
}
Err(other) => return Err(other.into()),
Ok(_) => {}
} Prevention
- Never ignore the Result of initialize; a failed build leaves stale state
- Re-run initialization to completion after any schedule mutation in runtime-editing scenarios
- Prefer the app/run path, which initializes schedules atomically before execution
When it happens
Trigger: A first `initialize` fails on a build error (cycle, cross-dependency), you fix the config, and re-trigger schedule internals while the graph is still marked stale; mutating a schedule mid-initialization; manually calling schedule plumbing without going through `Schedule::initialize`.
Common situations: Test harnesses that call schedule internals after an intentionally-broken build; app code that adds systems inside `Startup`/plugins while a schedule build previously failed; hot-reload-style schedules mutated at runtime between initialize passes.
Related errors
- Error when initializing schedule {:?}: {}
- executable schedule has not been built
- HierarchySort
- DependencySort
- FlatDependencySort
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/657cbe23017b0f45.
Report an issue: GitHub.