bevyengine/bevy · warning · AmbiguousSystemConflictsWarning
Systems with conflicting access have indeterminate run order
Error message
Systems with conflicting access have indeterminate run order: {:?} What it means
Warning emitted when a schedule is built with ScheduleBuildSettings::ambiguity_detection enabled and two or more systems have conflicting World access (they cannot run in parallel) but no explicit relative order, so which one runs first is nondeterministic. It is a warning, not a hard error: the schedule still builds and runs. The payload (ConflictingSystems) lists each pair and the component ids they clash on (empty list means a general World conflict, e.g. an exclusive system).
Source
Thrown at crates/bevy_ecs/src/schedule/node.rs:710
.map(|id| components.get_name(*id).unwrap())
.collect();
(name_a, name_b, conflict_names)
})
}
}
impl Deref for ConflictingSystems {
type Target = Vec<(SystemKey, SystemKey, Box<[ComponentId]>)>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// Error returned when there are ambiguous system conflicts detected.
#[derive(Error, Debug)]
#[error("Systems with conflicting access have indeterminate run order: {:?}", .0.0)]
pub struct AmbiguousSystemConflictsWarning(pub ConflictingSystems);
/// Container for system sets in a schedule.
#[derive(Default)]
pub struct SystemSets {
/// List of system sets in the schedule.
sets: SlotMap<SystemSetKey, InternedSystemSet>,
/// List of conditions for each system set, in the same order as `sets`.
conditions: SecondaryMap<SystemSetKey, Vec<ConditionWithAccess>>,
/// Map from system sets to their keys.
ids: HashMap<InternedSystemSet, SystemSetKey>,
/// System sets that have not been initialized yet.
uninit: Vec<UninitializedSet>,
}
/// A system set's conditions that have not been initialized yet.
struct UninitializedSet {
key: SystemSetKey,View on GitHub (pinned to 396ca72708)
Solutions
- Add an explicit order between the reported pair: .before()/.after(), put them in one .chain()ed tuple, or order their containing SystemSets.
- If the conflict is accidental, narrow one system's access (Changed<T>/Added<T> filters, disjoint components) so the accesses no longer conflict.
- If the order genuinely does not matter, leave ambiguity_detection off for that schedule (it is opt-in).
Example fix
// before app.add_systems(Update, (advance_timers, apply_damage)); // both &mut Health, no order // after app.add_systems(Update, (advance_timers, apply_damage).chain());
Defensive patterns
Strategy: validation
Validate before calling
// Detect ambiguity during development only
app.add_schedule(Update, Schedule::new(Update).set_build_settings(ScheduleBuildSettings {
ambiguity_detection: true,
..default()
})); Prevention
- Enable ambiguity detection in dev builds and treat new pairs as review blockers.
- Establish feature-level set ordering (e.g. InputSet, PhysicsSet) so cross-plugin order is explicit.
- Chain tuples that touch the same data.
When it happens
Trigger: Two systems with &mut access to the same component (or overlapping queries) added to the same schedule without .before/.after/.chain between them, while ambiguity detection is turned on for that schedule.
Common situations: Adding a new system that writes a component another system also writes; enabling ambiguity checks on a large existing app and getting a flood of pairs; cross-plugin systems that touch the same data with no shared set ordering.
Related errors
- Tried to order against `{0:?}` in a schedule that has more t
- self-loop detected at node `{0:?}`
- cycles detected: {0:?}
- HierarchySort
- DependencySort
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/0087e6e0c9a76bba.
Report an issue: GitHub.