bevyengine/bevy · critical

System input value was not found. Did you forget to initiali

Error message

System input value was not found. Did you forget to initialize the system before running it?

What it means

WithInputFromWrapper (created by IntoSystem::with_input_from) lazily constructs its input value in System::initialize via T::from_world(world). run_unsafe expects that to have happened; running the system before initialize leaves value as None and this expect panics. It is the use-before-initialize guard for lazily-created system inputs.

Source

Thrown at crates/bevy_ecs/src/system/schedule_system.rs:159

    fn name(&self) -> DebugName {
        self.system.name()
    }

    #[inline]
    fn flags(&self) -> SystemStateFlags {
        self.system.flags()
    }

    unsafe fn run_unsafe(
        &mut self,
        _input: SystemIn<'_, Self>,
        world: UnsafeWorldCell,
    ) -> Result<Self::Out, RunSystemError> {
        let value = self
            .value
            .as_mut()
            .expect("System input value was not found. Did you forget to initialize the system before running it?");
        // SAFETY: Upheld by caller
        unsafe { self.system.run_unsafe(value, world) }
    }

    #[cfg(feature = "hotpatching")]
    #[inline]
    fn refresh_hotpatch(&mut self) {
        self.system.refresh_hotpatch();
    }

    fn apply_deferred(&mut self, world: &mut World) {
        self.system.apply_deferred(world);
    }

    fn queue_deferred(&mut self, world: DeferredWorld) {
        self.system.queue_deferred(world);
    }

View on GitHub (pinned to 396ca72708)

Solutions

  1. Call system.initialize(&mut world) once before run_unsafe - schedules do this automatically on first run (initialize creates the value via T::from_world).
  2. Or use the eager variant: supply the value with .with_input(value) instead of with_input_from.
  3. For one-off runs, use safe helpers such as world.run_system_once which handle initialization.

Example fix

// before
let mut sys = my_system.with_input_from();
unsafe { sys.run_unsafe((), world.into()) }; // panic: input value never created

// after
let mut sys = my_system.with_input_from();
sys.initialize(&mut world); // creates the input via GameInput::from_world
unsafe { sys.run_unsafe((), world.into()) };
Defensive patterns

Strategy: validation

Validate before calling

if wrapper.value().is_none() {
    wrapper.initialize(&mut world); // triggers T::from_world and fills the value
}
// run only after the value exists

Prevention

When it happens

Trigger: Calling run_unsafe on a system produced with .with_input_from(..) before any initialize call: manual runs in tests/tools, custom executors that skip initialization, or scheduling code that bypasses the normal initialize-then-run order.

Common situations: Running piped-input systems manually outside schedules; executors that run systems without initializing them first; porting from eagerly-supplied inputs to with_input_from without adding an initialization step.

Related errors


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/441643556f0ece37. Report an issue: GitHub.