bevyengine/bevy · error

B0007

B0007

Error message

error[{}]: `{}` and `{}` parameters in system `{}` conflict{}.
Consider:
{}* Merging conflicting parameters into a `ParamSet`
See: https://bevy.org/learn/errors/{}

What it means

panic_for_param_conflict (B0007) fires at system initialization when two system parameters declare incompatible accesses to the same component — e.g. Query<&mut T> and ResMut<Vec<T>>-like overlaps, or two &mut queries on the same component. The message lists both parameters, suggestions, and links the Bevy error page.

Solutions

  1. Merge conflicting parameters into a single Query or ParamSet
  2. Use disjoint filters (With/Without/Changed) to make accesses provably disjoint
  3. Read-only access is fine in parallel — drop the extra &mut if you only read
  4. Split the system into multiple systems that run sequentially

Example fix

// before
fn system(q1: Query<&mut Transform>, q2: Query<&mut Transform, With<Player>>) {}

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

Strategy: try-catch

Try / catch

let result = std::panic::catch_unwind(|| system.initialize(&mut world));
if result.is_err() { eprintln!("System has B0007 param conflict — use ParamSet"); }

Prevention

When it happens

Trigger: fn system(q1: Query<&mut Transform>, q2: Query<&Transform>) or two ResMut< resource> of the same resource, or &mut T plus EventReader/Writer overlaps; conflict detected in init_param_or_panic during system.init().

Common situations: Two queries with overlapping mutable component access; Query<&mut T> alongside an event writer for a component resource; adding a second system parameter that aliases an existing one during refactoring.

Related errors


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

Appendix: source

Thrown at crates/bevy_ecs/src/system/function_system.rs:643

    let remove_duplicate = (err1.param == err2.param && err1.access == err2.access)
        .then_some(DebugName::borrowed("Removing the duplicate parameter"));

    let mut suggestions = err1
        .suggestions
        .iter()
        .chain(&err2.suggestions)
        .collect::<Vec<_>>();
    // Remove duplicate suggestions so that we don't suggest "Using `Without<T>`" twice for conflicting queries.
    suggestions.sort_by_key(|s| &***s);
    suggestions.dedup();

    let suggestions = suggestions
        .into_iter()
        .chain(&remove_duplicate)
        .map(|s| format!("* {s}\n"))
        .collect::<String>();

    panic!(
        concat!(
            "error[{}]: `{}` and `{}` parameters in system `{}` conflict{}.\n",
            "Consider:\n",
            "{}",
            "* Merging conflicting parameters into a `ParamSet`\n",
            "See: https://bevy.org/learn/errors/{}",
        ),
        code,
        err1.param.shortname(),
        err2.param.shortname(),
        system_name,
        accesses,
        suggestions,
        code_lower,
    );
}

/// Formats a simple panic message for conflicting [`SystemParam`] access when debug strings are not available.

View on GitHub (pinned to a62cce8c05)