bevyengine/bevy · error
Cannot call `ReflectComponent::reflect_unchecked_mut` on com
Error message
Cannot call `ReflectComponent::reflect_unchecked_mut` on component {name}. It is immutable, and cannot modified through reflection What it means
`reflect_unchecked_mut` is the unsafe variant of `ReflectComponent`'s mutable access: it skips aliasing checks and directly returns a `&mut dyn Reflect` for the component. Like `reflect_mut`, it is guarded by the component's declared mutability — for a component with `type Mutability = Immutable`, the guard panics rather than let reflection break the immutability contract, even though the caller already opted into `unsafe`.
Source
Thrown at crates/bevy_ecs/src/reflect/component.rs:393
reflect_mut: |entity| {
if !C::Mutability::MUTABLE {
let name = DebugName::type_name::<C>();
let name = name.shortname();
panic!("Cannot call `ReflectComponent::reflect_mut` on component {name}. It is immutable, and cannot modified through reflection");
}
// SAFETY: guard ensures `C` is a mutable component
unsafe {
entity
.into_mut_assume_mutable::<C>()
.map(|c| c.map_unchanged(|value| value as &mut dyn Reflect))
}
},
reflect_unchecked_mut: |entity| {
if !C::Mutability::MUTABLE {
let name = DebugName::type_name::<C>();
let name = name.shortname();
panic!("Cannot call `ReflectComponent::reflect_unchecked_mut` on component {name}. It is immutable, and cannot modified through reflection");
}
// SAFETY: reflect_unchecked_mut is an unsafe function pointer used by
// `reflect_unchecked_mut` which must be called with an UnsafeEntityCell with access to the component `C` on the `entity`
// guard ensures `C` is a mutable component
let c = unsafe { entity.get_mut_assume_mutable::<C>() };
c.map(|c| c.map_unchanged(|value| value as &mut dyn Reflect))
},
register_component: |world: &mut World| -> ComponentId {
world.register_component::<C>()
},
map_entities: |reflect: &mut dyn Reflect, mut mapper: &mut dyn EntityMapper| {
let component = reflect.downcast_mut::<C>().unwrap();
Component::map_entities(component, &mut mapper);
},
})
}
}View on GitHub (pinned to 396ca72708)
Solutions
- Switch to the immutable workflow: `reflect()` to read, construct the replacement value, `insert()` to write
- If the component genuinely needs reflective mutation, declare `type Mutability = Mutable` in its `Component` impl
- Guard tooling loops so immutable components are filtered out before the unsafe call
Example fix
// before
let c = unsafe { reflect_component.reflect_unchecked_mut(entity_cell) }; // panics for Immutable
// after — make the component mutable, or replace instead of mutating
impl Component for Marker { type Mutability = Mutable; } Defensive patterns
Strategy: validation
Validate before calling
// Before the unchecked path, verify the component's mutability
if <C as Component>::Mutability::MUTABLE {
let c = unsafe { reflect_component.reflect_unchecked_mut(entity_cell) };
} else {
// read-only path: reflect() then insert() a replacement
} Type guard
fn is_reflect_mutable<C: Component>() -> bool { C::Mutability::MUTABLE } Prevention
- Audit every unsafe reflect_unchecked_mut call site for the mutability precondition — the unsafe contract does not cover it
- Keep a static list of immutable components when writing generic tooling
- Run editor flows against a fixture entity set that includes known-immutable components (e.g. ChildOf) in CI
When it happens
Trigger: Calling `ReflectComponent::reflect_unchecked_mut` (or an `UnsafeEntityCell`-based reflective mutation path) on a component whose `Component::Mutability` is `Immutable` — typically deep editor, scene-spawn, or framework code that uses the unchecked API for performance on all components.
Common situations: Porting internal tooling from Bevy versions before mutable/immutable components existed (all components were mutable); inspector or replay tools that iterate every registered `ReflectComponent` and call the unchecked mutator; user hierarchies built on `ChildOf` (immutable) being edited reflectively.
Related errors
- Cannot call `ReflectComponent::reflect_mut` on component {na
- component should represent a type.
- `{type_path}` should be registered in type registry via `App
- `{type_path}` should have #[reflect(Component)] or #[reflect
- Couldn't create an instance of `{name}` using the reflected
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/990e73587bf225c9.
Report an issue: GitHub.