bevyengine/bevy · critical
ParamSet parameter validation failed: {err}
Error message
ParamSet parameter validation failed: {err} What it means
ParamSet exposes its members through p0()..p7(); each accessor builds the member param from stored state via get_param and panics if that returns an error. The wrapped {err} is the concrete parameter validation failure - most commonly a required Res<T>/ResMut<T> inside the ParamSet whose resource does not exist in the World at call time (or state built for a different world).
Source
Thrown at crates/bevy_ecs/src/system/system_param.rs:658
})
}
}
impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)>
{
$(
/// Gets exclusive access to the parameter at index
#[doc = stringify!($index)]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> {
// SAFETY: systems run without conflicts with other systems.
// Conflicting params in ParamSet are not accessible at the same time
// ParamSets are guaranteed to not conflict with other SystemParams
unsafe {
$param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick)
}
.unwrap_or_else(|err| panic!("ParamSet parameter validation failed: {err}"))
}
)*
}
}
}
all_tuples_enumerated!(impl_param_set, 1, 8, P, p);
// SAFETY: Res only reads a single World resource
unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {}
// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res
// conflicts with any prior access, a panic will occur.
unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
type State = ComponentId;
type Item<'w, 's> = Res<'w, T>;
fn init_state(world: &mut World) -> Self::State {View on GitHub (pinned to 396ca72708)
Solutions
- Read the {err} text embedded in the panic - it names the exact failing param and reason.
- Insert required resources at startup (app.init_resource / insert_resource) before any schedule using them runs.
- If presence is genuinely optional, make that member Option<Res<T>>/Option<ResMut<T>> inside the ParamSet and handle None.
Example fix
// before
fn sys(mut p: ParamSet<(ResMut<Score>, Res<Config>)>) {
let cfg = *p.p1(); // panics if Config was never inserted
}
// after
fn sys(mut p: ParamSet<(ResMut<Score>, Option<Res<Config>>)>) {
let cfg = p.p1().as_deref().copied().unwrap_or_default();
} Defensive patterns
Strategy: validation
Validate before calling
if !world.contains_resource::<Config>() {
world.init_resource::<Config>();
}
// safe to fetch a ParamSet member that is Res<Config> Prevention
- Use Option<Res<T>> inside ParamSets for any resource not guaranteed present.
- init_resource/insert_resource at app setup for all required resources.
- When Commands insert resources, apply deferred (or order systems) before dependent access.
When it happens
Trigger: Calling param_set.pN() where the member is Res/ResMut of a resource that was never inserted or was removed; resources inserted via Commands by an earlier system that have not been flushed (apply_deferred not yet run) when the ParamSet member is fetched.
Common situations: Systems scheduled before the system that inserts the resource; resources created lazily by other plugins; tests running param code against partially built worlds.
Related errors
- resource does not exist: {}
- Resource `{}` was inserted during a call to World::resource_
- 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
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/6f201b62faeac15d.
Report an issue: GitHub.