bevyengine/bevy · error

` ` has access conflicts between nested queries .

Error message

`{}` has access conflicts between nested queries{accesses}.

What it means

This panic comes from assert_no_conflicts_with_nested_queries on SystemState/QueryState: when a system/state contains nested queries (e.g. Query with Query inside), their component accesses overlap incompatibly (mut & read or two muts on the same components). Bevy detects the conflicting Access pairs at init and panics with the formatted conflict list.

Solutions

  1. Split the conflicting accesses into disjoint components or use filters (With/Without) so accesses don't overlap
  2. Wrap one of the conflicting queries in ParamSet
  3. Restructure so the nested query only conflicts on entities via Without<Parent>-style exclusion

Example fix

// before
fn system(q: Query<(Entity, &mut Transform, Query<&GlobalTransform>)>) {}

// after
fn system(mut set: ParamSet<(Query<&mut Transform>, Query<&GlobalTransform>)>) {}
Defensive patterns

Strategy: try-catch

Try / catch

// Conflict is a hard panic at system init — catch via std::panic::catch_unwind during init in test harnesses:
let result = std::panic::catch_unwind(|| system.initialize(&mut world));

Prevention

When it happens

Trigger: Declaring Query<(Query<&mut A>, &A)> or Query<(&mut A, Query<&A>)> (or param sets with nested queries) whose flattened accesses conflict; initializing the system triggers the check.

Common situations: Nesting queries inside a Query tuple for parent/child traversal and requesting the same component mutable in one and readable/mutable in the other.

Related errors


AI-assisted analysis of bevyengine/bevy@a62cce8c05 (2026-09-19). Data as JSON: /api/errors/b8e44564ac6126d4. Report an issue: GitHub.

Appendix: source

Thrown at crates/bevy_ecs/src/query/state.rs:351

    }

    fn assert_no_conflicts_with_nested_queries(&self, world: UnsafeWorldCell<'_>) {
        self.init_access(&mut FilteredAccessSet::new())
            .unwrap_or_else(|access2| {
                // Find the other conflicting query.
                // By initializing `access` with the access of the later query,
                // the earlier one will detect the conflict instead.
                let mut access = access2.clone();
                let access1 = self.init_access(&mut access).expect_err(
                    "Query with internal access conflict must always report a conflict",
                );
                let conflicts = access1.get_conflicts(&access2);
                let mut accesses = conflicts.format_conflict_list(world);
                // Access list may be empty (if access to all components requested)
                if !accesses.is_empty() {
                    accesses.insert_str(0, " on component(s) ");
                }
                panic!(
                    "`{}` has access conflicts between nested queries{accesses}.",
                    DebugName::type_name::<Self>().shortname()
                );
            });
    }

    /// Creates a [`Query`] from the given [`QueryState`] and [`World`].
    ///
    /// This will create read-only queries, see [`Self::query_mut`] for mutable queries.
    pub fn query<'w, 's>(&'s mut self, world: &'w World) -> Query<'w, 's, D::ReadOnly, F> {
        self.update_archetypes(world);
        self.query_manual(world)
    }

    /// Creates a [`Query`] from the given [`QueryState`] and [`World`].
    ///
    /// This method is slightly more efficient than [`QueryState::query`] in some situations, since
    /// it does not update this instance's internal cache. The resulting query may skip an entity that

View on GitHub (pinned to a62cce8c05)