bevyengine/bevy · error · ScheduleBuildError
DependencySort
DependencySort
Error message
Failed to topologically sort the dependency graph: {0} What it means
The dependency graph holds the `before`/`after` ordering constraints between systems and sets. `DependencySort` means that graph has a cycle: the ordering constraints form a loop, so no execution order satisfies them. This surfaces from `Schedule::initialize`, typically on the first run of the schedule.
Source
Thrown at crates/bevy_ecs/src/schedule/error.rs:27
graph::{
DagCrossDependencyError, DagOverlappingGroupError, DagRedundancyError,
DiGraphToposortError, GraphNodeId,
},
AmbiguousSystemConflictsWarning, ConflictingSystems, NodeId, ScheduleGraph, SystemKey,
SystemSetKey, SystemTypeSetAmbiguityError,
},
world::World,
};
/// Category of errors encountered during [`Schedule::initialize`](crate::schedule::Schedule::initialize).
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum ScheduleBuildError {
/// Tried to topologically sort the hierarchy of system sets.
#[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)]View on GitHub (pinned to 396ca72708)
Solutions
- Remove one edge in the reported cycle — the error identifies the nodes where topological sort stalled; map them back to the systems/sets
- Audit plugin boundaries for symmetric before/after pairs and pick a single direction
- Prefer `.in_set` plus one owner of ordering per relationship instead of ad-hoc pairwise `.before`/`.after`
Example fix
// before app.add_systems(Update, (a.before(b), b.before(a))); // cycle // after app.add_systems(Update, (a.before(b),));
Defensive patterns
Strategy: try-catch
Validate before calling
// Before adding symmetric ordering, check the inverse edge in your own config model
// or just attempt an early initialize in dev builds:
#[cfg(test)]
fn assert_builds(schedule: &mut Schedule, world: &mut World) {
schedule.initialize(world).expect("schedule must build");
} Try / catch
match schedule.initialize(&mut world) {
Err(ScheduleBuildError::DependencySort(err)) => {
// err identifies the NodeId where ordering constraints cycled; remove one .before/.after edge
}
other => other.map(|_| ()),
} Prevention
- Prefer ordering sets once instead of pairwise system orderings scattered across plugins
- Avoid mutual before/after when integrating two plugins — pick one direction
- Add a test that builds the full app schedule graph on CI
When it happens
Trigger: `a.before(b)` together with `b.before(a)` (or a longer transitive chain a→b→c→a); symmetric `.before`/`.after` introduced when merging plugins that each order against the other's systems; a set ordered before one of its own members indirectly.
Common situations: Two plugins mutually ordering their systems for 'safety'; incremental addition of ordering constraints over time that accidentally closes a loop; conditional ordering macros that expand to more edges than expected.
Related errors
- FlatDependencySort
- HierarchySort
- CrossDependency
- SetsHaveOrderButIntersect
- DAG has a cross-dependency between nodes {0:?} and {1:?}
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/f4c9f2f7e50f8e82.
Report an issue: GitHub.