bevyengine/bevy · critical
Encountered a mismatched World. This SystemState was created
Error message
Encountered a mismatched World. This SystemState was created from {this:?}, but a method was called using {other:?}. What it means
SystemState caches a system's parameter state and is bound to the WorldId of the World it was built from. validate_world panics when a SystemState method is invoked against a World with a different id, because the cached state would be invalid for that world. This is bevy's guard against silently reusing per-world caches across worlds.
Source
Thrown at crates/bevy_ecs/src/system/function_system.rs:423
Param::apply(&mut self.param_state, &self.meta, world);
}
/// Returns `true` if `world_id` matches the [`World`] that was used to call [`SystemState::new`].
/// Otherwise, this returns false.
#[inline]
pub fn matches_world(&self, world_id: WorldId) -> bool {
self.world_id == world_id
}
/// Asserts that the [`SystemState`] matches the provided world.
#[inline]
#[track_caller]
fn validate_world(&self, world_id: WorldId) {
#[inline(never)]
#[track_caller]
#[cold]
fn panic_mismatched(this: WorldId, other: WorldId) -> ! {
panic!("Encountered a mismatched World. This SystemState was created from {this:?}, but a method was called using {other:?}.");
}
if !self.matches_world(world_id) {
panic_mismatched(self.world_id, world_id);
}
}
/// Retrieve the [`SystemParam`] values.
///
/// Returns an error if system parameter validation fails.
///
/// # Safety
/// This call might access any of the input parameters in a way that violates Rust's mutability rules. Make sure the data
/// access is safe in the context of global [`World`] access. The passed-in [`World`] _must_ be the [`World`] the [`SystemState`] was
/// created with.
#[inline]
#[track_caller]
pub unsafe fn get_unchecked<'w, 's>(View on GitHub (pinned to 396ca72708)
Solutions
- Store the WorldId next to the state and rebuild whenever SystemState::matches_world(world.id()) is false.
- Do not cache SystemState in statics/globals across App instances; key it per world or construct it per call site.
- In tests, create a fresh SystemState per test/world.
Example fix
// before
static mut STATE: Option<SystemState<Query<&Transform>>> = None; // reused across Worlds
// after
struct Cached {
world_id: WorldId,
state: SystemState<Query<'static, 'static, &'static Transform>>,
}
fn cached(world: &mut World, slot: &mut Option<Cached>) -> &mut Cached {
let id = world.id();
if !slot.as_ref().is_some_and(|c| c.world_id == id) {
*slot = Some(Cached { world_id: id, state: SystemState::new(world) });
}
slot.as_mut().unwrap()
} Defensive patterns
Strategy: type-guard
Validate before calling
if !state.matches_world(world.id()) {
*state = SystemState::new(world); // rebuild the cache for this world
}
// safe to call state.get_mut(world) Type guard
fn state_matches_world<S: SystemParam>(state: &SystemState<S>, world: &World) -> bool {
state.matches_world(world.id())
} Prevention
- Pair every cached SystemState with the WorldId it was built from.
- Avoid static/global SystemState caches shared across App instances.
- In helpers, take &mut World and derive the state from it instead of reusing cached state.
When it happens
Trigger: Creating SystemState<Q> with one World and calling .get()/.get_mut() with another: static or cached state shared across two App/World instances, state extracted in a helper and reused after the world was rebuilt, or multi-world setups (editor preview world plus main world) sharing one state.
Common situations: Static/cached SystemState reused across tests that each create their own App; performance-motivated state caches that outlive their world; refactors that move world-creating code while keeping the cache.
Related errors
- resource does not exist: {}
- Cannot call `ReflectComponent::reflect_mut` on component {na
- Cannot call `ReflectComponent::reflect_unchecked_mut` on com
- Resource entity {} of {} has been despawned, when it's not s
- System with key {:?} does not exist in the schedule
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/6dcfe9112dd51436.
Report an issue: GitHub.