bevyengine/bevy · critical
BuilderSystem {} was not initialized before calling run_unsa
Error message
BuilderSystem {} was not initialized before calling run_unsafe. What it means
Systems assembled with the SystemBuilder API transition from Uninitialized to Initialized when System::initialize runs (which schedules do on first execution). This panic fires when run_unsafe is called on a BuilderSystem that is still Uninitialized - its inner system, params, and pointers were never set up against a World.
Source
Thrown at crates/bevy_ecs/src/system/builder.rs:390
match &self.inner {
BuilderSystemInner::Initialized { system, .. } => system.flags(),
BuilderSystemInner::Uninitialized { meta, .. } => meta.flags(),
BuilderSystemInner::Invalid => unreachable!(),
}
}
#[inline]
unsafe fn run_unsafe(
&mut self,
input: super::SystemIn<'_, Self>,
world: UnsafeWorldCell,
) -> Result<Self::Out, RunSystemError> {
match &mut self.inner {
// SAFETY: requirements upheld by the caller.
BuilderSystemInner::Initialized { system, .. } => unsafe {
system.run_unsafe(input, world)
},
BuilderSystemInner::Uninitialized { .. } => panic!(
"BuilderSystem {} was not initialized before calling run_unsafe.",
self.name()
),
BuilderSystemInner::Invalid => unreachable!(),
}
}
#[cfg(feature = "hotpatching")]
#[inline]
fn refresh_hotpatch(&mut self) {
match &mut self.inner {
BuilderSystemInner::Initialized { system, .. } => system.refresh_hotpatch(),
BuilderSystemInner::Uninitialized { .. } => {}
BuilderSystemInner::Invalid => unreachable!(),
}
}
#[inline]View on GitHub (pinned to 396ca72708)
Solutions
- Call system.initialize(&mut world) once before the first run_unsafe - the built-in schedules do this for you.
- Prefer safe entry points (world.run_system_once, app.add_systems) over manual run_unsafe.
- When writing an executor, mirror bevy's own executors: initialize all systems during schedule initialization, then run them.
Example fix
// before
let mut system = SystemBuilder::<()>::new(&mut world).build(my_fn);
unsafe { system.run_unsafe((), world.into()) }; // panic: Uninitialized
// after
let mut system = SystemBuilder::<()>::new(&mut world).build(my_fn);
system.initialize(&mut world);
unsafe { system.run_unsafe((), world.into()) }; Defensive patterns
Strategy: validation
Validate before calling
// WithInputFromWrapper exposes its state before running:
if wrapper.value().is_none() {
wrapper.initialize(&mut world);
}
// generally: initialize every system once before any run_unsafe Prevention
- Always call system.initialize(&mut world) once before run_unsafe, or rely on schedules.
- Avoid manual run_unsafe; use world.run_system_once or add_systems.
- Executor authors: copy bevy's built-in executors' initialize-then-run pattern.
When it happens
Trigger: Manually invoking run_unsafe on a builder-built system without a prior initialize call: custom executors running BoxedSystems directly, test helpers executing systems outside a schedule, or middleware that wraps and runs systems while bypassing initialization.
Common situations: Custom executors that skip the initialize step; systems built with SystemBuilder cached in resources and run manually; porting code from function systems (which tolerate some misuse) to the builder API.
Related errors
- System input value was not found. Did you forget to initiali
- Error when initializing schedule {:?}: {}
- 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/da5c1d33c4f6bf8e.
Report an issue: GitHub.