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::Ignore

View on GitHub (pinned to 396ca72708)

Solutions

  1. 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
  2. When calling `schedule.initialize(world)` manually, handle the `Result` and fix the first reported build error so initialization completes instead of leaving partial state
  3. 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

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


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