{"record":{"id":"bef1191fd6cd0439","repo":"bevyengine/bevy","slug":"cannot-call-reflectcomponent-reflect-mut-on-com","errorCode":null,"errorMessage":"Cannot call `ReflectComponent::reflect_mut` on component {name}. It is immutable, and cannot modified through reflection","messagePattern":"Cannot call `ReflectComponent::reflect_mut` on component (.+?)\\. It is immutable, and cannot modified through reflection","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bevy_ecs/src/reflect/component.rs","lineNumber":379,"sourceCode":"                entity\n                    .take::<C>()\n                    .map(|component| Box::new(component).into_reflect())\n            },\n            contains: |entity| entity.contains::<C>(),\n            copy: |source_world, destination_world, source_entity, destination_entity, registry| {\n                let source_component = source_world.get::<C>(source_entity).unwrap();\n                let destination_component =\n                    from_reflect_with_fallback::<C>(source_component, destination_world, registry);\n                destination_world\n                    .entity_mut(destination_entity)\n                    .insert(destination_component);\n            },\n            reflect: |entity| entity.get::<C>().map(|c| c as &dyn Reflect),\n            reflect_mut: |entity| {\n                if !C::Mutability::MUTABLE {\n                    let name = DebugName::type_name::<C>();\n                    let name = name.shortname();\n                    panic!(\"Cannot call `ReflectComponent::reflect_mut` on component {name}. It is immutable, and cannot modified through reflection\");\n                }\n\n                // SAFETY: guard ensures `C` is a mutable component\n                unsafe {\n                    entity\n                        .into_mut_assume_mutable::<C>()\n                        .map(|c| c.map_unchanged(|value| value as &mut dyn Reflect))\n                }\n            },\n            reflect_unchecked_mut: |entity| {\n                if !C::Mutability::MUTABLE {\n                    let name = DebugName::type_name::<C>();\n                    let name = name.shortname();\n                    panic!(\"Cannot call `ReflectComponent::reflect_unchecked_mut` on component {name}. It is immutable, and cannot modified through reflection\");\n                }\n\n                // SAFETY: reflect_unchecked_mut is an unsafe function pointer used by\n                // `reflect_unchecked_mut` which must be called with an UnsafeEntityCell with access to the component `C` on the `entity`","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_ecs/src/reflect/component.rs#L361-L397","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n#[derive(Component, Reflect)]\n#[reflect(Component)]\nstruct Health(f32);\nimpl Component for Health { type Mutability = Immutable; }\nlet reflected = reflect_component.reflect_mut(&mut entity); // panics\n\n// after — allow reflective mutation\nimpl Component for Health { type Mutability = Mutable; }","handlingStrategy":"validation","validationCode":"// Statically-known component: check mutability before the mutable path\nfn can_reflect_mut<C: Component>() -> bool {\n    <C as Component>::Mutability::MUTABLE\n}\n\nif can_reflect_mut::<MyComponent>() {\n    let r = reflect_component.reflect_mut(&mut entity_mut);\n} else {\n    let r = reflect_component.reflect(&entity);\n    // build replacement and reflect_component.insert(...) instead\n}","typeGuard":"fn is_reflect_mutable<C: Component>() -> bool { C::Mutability::MUTABLE }","tryCatchPattern":null,"preventionTips":["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"],"tags":["bevy","ecs","reflection","immutability","panic"],"backgroundTag":"immutable-component-mutation","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}