bevyengine/bevy · error
Cannot call `ReflectComponent::reflect_mut` on component {na
Error message
Cannot call `ReflectComponent::reflect_mut` on component {name}. It is immutable, and cannot modified through reflection What it means
Bevy's `ReflectComponent` exposes a component on an entity for reflective access. `reflect_mut` is the path that hands out a `&mut dyn Reflect` for in-place editing, but components can declare `type Mutability = Immutable` in their `Component` impl to opt out. When the registered component's `C::Mutability::MUTABLE` is false, this closure panics instead of returning a mutable reference, because handing one out would bypass the immutability guarantee the type declared.
Source
Thrown at crates/bevy_ecs/src/reflect/component.rs:379
entity
.take::<C>()
.map(|component| Box::new(component).into_reflect())
},
contains: |entity| entity.contains::<C>(),
copy: |source_world, destination_world, source_entity, destination_entity, registry| {
let source_component = source_world.get::<C>(source_entity).unwrap();
let destination_component =
from_reflect_with_fallback::<C>(source_component, destination_world, registry);
destination_world
.entity_mut(destination_entity)
.insert(destination_component);
},
reflect: |entity| entity.get::<C>().map(|c| c as &dyn Reflect),
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`View on GitHub (pinned to 396ca72708)
Solutions
- Use the immutable path: read via `ReflectComponent::reflect`, build the new value, then replace it with `ReflectComponent::insert` (remove + insert, never in-place mutation)
- If in-place reflective mutation is a real requirement, change the component's definition to `type Mutability = Mutable`
- In editor/tooling code, check `C::Mutability::MUTABLE` (statically) or maintain a skip-list of immutable components and present them as read-only
Example fix
// before
#[derive(Component, Reflect)]
#[reflect(Component)]
struct Health(f32);
impl Component for Health { type Mutability = Immutable; }
let reflected = reflect_component.reflect_mut(&mut entity); // panics
// after — allow reflective mutation
impl Component for Health { type Mutability = Mutable; } Defensive patterns
Strategy: validation
Validate before calling
// Statically-known component: check mutability before the mutable path
fn can_reflect_mut<C: Component>() -> bool {
<C as Component>::Mutability::MUTABLE
}
if can_reflect_mut::<MyComponent>() {
let r = reflect_component.reflect_mut(&mut entity_mut);
} else {
let r = reflect_component.reflect(&entity);
// build replacement and reflect_component.insert(...) instead
} Type guard
fn is_reflect_mutable<C: Component>() -> bool { C::Mutability::MUTABLE } Prevention
- Decide per component whether reflective mutation is allowed and set Mutability accordingly at definition time
- In editor tooling, treat components without Mutable mutability as read-only fields
- Prefer replace-via-insert workflows over in-place reflect_mut for shared/generic code
When it happens
Trigger: Calling `ReflectComponent::reflect_mut` (or any `ReflectMut`-based editing path) on a component declared `Immutable` — e.g. an editor/inspector crate mutating every component on an entity via reflection, hitting a component like `ChildOf` that Bevy defines as immutable, or user code doing `registry`-driven component patching that assumes all components are mutable.
Common situations: Using bevy_editor_pls / bevy_inspector_egui or custom scene tooling on a codebase that adopted immutable components (Bevy 0.15+); upgrading a project where a component was changed to Immutable while generic reflection code still calls reflect_mut on it; serializers that apply patches to all registered components indiscriminately.
Related errors
- Cannot call `ReflectComponent::reflect_unchecked_mut` on com
- 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/bef1191fd6cd0439.
Report an issue: GitHub.