bevyengine/bevy · error · DagOverlappingGroupError
DAG has overlapping groups between keys {0:?} and {1:?}
Error message
DAG has overlapping groups between keys {0:?} and {1:?} What it means
`DagOverlappingGroupError` is the low-level graph error reporting that groups keyed `{0}` and `{1}` have overlapping members while also carrying an ordering between the group keys. Bevy wraps it as `ScheduleBuildError::SetsHaveOrderButIntersect`: two ordered system sets share at least one system, so that system has no consistent position.
Source
Thrown at crates/bevy_ecs/src/schedule/graph/dag.rs:724
impl<K: Debug, V: Debug, S> Debug for DagGroups<K, V, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DagGroups").field(&self.0).finish()
}
}
/// Error indicating that the graph has redundant edges.
#[derive(Error, Debug)]
#[error("DAG has redundant edges: {0:?}")]
pub struct DagRedundancyError<N: GraphNodeId>(pub Vec<(N, N)>);
/// Error indicating that two graphs both have a dependency between the same nodes.
#[derive(Error, Debug)]
#[error("DAG has a cross-dependency between nodes {0:?} and {1:?}")]
pub struct DagCrossDependencyError<N>(pub N, pub N);
/// Error indicating that the graph has overlapping groups between two keys.
#[derive(Error, Debug)]
#[error("DAG has overlapping groups between keys {0:?} and {1:?}")]
pub struct DagOverlappingGroupError<K>(pub K, pub K);
#[cfg(test)]
mod tests {
use core::ops::DerefMut;
use crate::schedule::graph::{index, Dag, Direction, GraphNodeId, UnGraph};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct TestNode(u32);
impl GraphNodeId for TestNode {
type Adjacent = (TestNode, Direction);
type Edge = (TestNode, TestNode);
fn kind(&self) -> &'static str {
"test node"
}View on GitHub (pinned to 396ca72708)
Solutions
- Give each system a single membership among the two ordered sets
- Remove the ordering between the intersecting sets, ordering specific non-shared systems instead
- Factor shared systems into a third set that both original sets relate to without intersection
Example fix
// before app.configure_sets(Update, A.before(B)); app.add_systems(Update, shared.in_set(A).in_set(B)); // DagOverlappingGroupError(A, B) // after app.configure_sets(Update, A.before(B)); app.add_systems(Update, shared.in_set(A));
Defensive patterns
Strategy: try-catch
Validate before calling
// Guard at config time: ordered sets must be disjoint
fn safe_to_order(a: &SetMembers, b: &SetMembers) -> bool {
a.intersection(b).next().is_none()
} Try / catch
match schedule.initialize(&mut world) {
Err(ScheduleBuildError::SetsHaveOrderButIntersect(err @ DagOverlappingGroupError(_, _))) => {
// err.0/err.1 name the two set keys; remove the shared membership or the ordering
}
other => other.map(|_| ()),
} Prevention
- Assign each system one home among ordered sets; use extra sets only when unordered
- Cross-cutting concerns should not be ordered against phase sets that share their members
- Integration-test set ordering whenever a new cross-cutting set is introduced
When it happens
Trigger: The same condition as `SetsHaveOrderButIntersect` — sets A and B with `A.before(B)` (possibly transitively) and at least one system registered in both. Encountered raw when matching the inner error or using the Dag grouping API directly.
Common situations: Cross-cutting sets (debug/networking) collecting systems that also live in ordered phase sets; plugin composition layering multiple memberships per system; refactors adding a second `.in_set` without checking the sets are unordered relative to each other.
Related errors
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/2b3e6a2eaa13015b.
Report an issue: GitHub.