bevyengine/bevy · error
Component already has an on_insert hook
Error message
Component already has an on_insert hook
What it means
Panic in ComponentLifecycleHook registration (on_insert): the try_on_insert call found an existing on_insert hook in the component's lifecycle slot. The expect guard prevents a second registration from overwriting the first, which would hide a real bug in hook wiring.
Source
Thrown at crates/bevy_ecs/src/lifecycle.rs:207
.expect("Component already has an on_add hook")
}
/// Register a [`ComponentHook`] that will be run when this component is added (with `.insert`)
/// or replaced.
///
/// An `on_insert` hook always runs after any `on_add` hooks (if the entity didn't already have the component).
///
/// # Warning
///
/// The hook won't run if the component is already present and is only mutated, such as in a system via a query.
/// As a result, this needs to be combined with immutable components to serve as a mechanism for reliably updating indexes and other caches.
///
/// # Panics
///
/// Will panic if the component already has an `on_insert` hook
pub fn on_insert(&mut self, hook: ComponentHook) -> &mut Self {
self.try_on_insert(hook)
.expect("Component already has an on_insert hook")
}
/// Register a [`ComponentHook`] that will be run when this component is about to be dropped,
/// such as being replaced (with `.insert`) or removed.
///
/// If this component is inserted onto an entity that already has it, this hook will run before the value is replaced,
/// allowing access to the previous data just before it is dropped.
/// This hook does *not* run if the entity did not already have this component.
///
/// An `on_discard` hook always runs before any `on_remove` hooks (if the component is being removed from the entity).
///
/// # Warning
///
/// The hook won't run if the component is already present and is only mutated, such as in a system via a query.
/// As a result, this needs to be combined with immutable components to serve as a mechanism for reliably updating indexes and other caches.
///
/// # Panics
///View on GitHub (pinned to 396ca72708)
Solutions
- Merge the new behavior into the already-registered on_insert hook closure
- Audit plugins/extension traits for duplicate .on_insert(...) calls on the same component
- Use try_on_insert and handle the None case explicitly when conflict is expected
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/bevy_ecs/src/lifecycle.rs:207 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/783a4a001538cdcb.
Report an issue: GitHub.