bevyengine/bevy · error

Error calling hotpatched system. Run a full rebuild

Error message

Error calling hotpatched system. Run a full rebuild

What it means

With the hotpatching feature, function systems are invoked through subsecond jump-table function pointers (HotFn::try_call_with_ptr). This expect fires when the stored current_ptr does not match the current jump table - i.e. a hot patch invalidated the pointer and refresh_hotpatch has not updated this system since. The panic message prescribes a full rebuild.

Source

Thrown at crates/bevy_ecs/src/system/function_system.rs:692

        let state = self.state.as_mut().expect(Self::ERROR_UNINITIALIZED);
        assert_eq!(state.world_id, world.id(), "Encountered a mismatched World. A System cannot be used with Worlds other than the one it was initialized with.");
        // SAFETY:
        // - The above assert ensures the world matches.
        // - All world accesses used by `F::Param` have been registered, so the caller
        //   will ensure that there are no data access conflicts.
        let params = unsafe {
            F::Param::get_param(&mut state.param, &self.system_meta, world, change_tick)
        }?;

        #[cfg(feature = "hotpatching")]
        let out = {
            let mut hot_fn = subsecond::HotFn::current(<F as SystemParamFunction<Marker>>::run);
            // SAFETY:
            // - pointer used to call is from the current jump table
            unsafe {
                hot_fn
                    .try_call_with_ptr(self.current_ptr, (&mut self.func, input, params))
                    .expect("Error calling hotpatched system. Run a full rebuild")
            }
        };
        #[cfg(not(feature = "hotpatching"))]
        let out = self.func.run(input, params);

        self.system_meta.last_run = change_tick;
        IntoResult::into_result(out)
    }

    #[cfg(feature = "hotpatching")]
    #[inline]
    fn refresh_hotpatch(&mut self) {
        let new = subsecond::HotFn::current(<F as SystemParamFunction<Marker>>::run).ptr_address();
        if new != self.current_ptr {
            log::debug!("system {} hotpatched", self.name());
        }
        self.current_ptr = new;
    }

View on GitHub (pinned to 396ca72708)

Solutions

  1. Perform a full rebuild/restart so all jump tables and cached pointers are recreated.
  2. Let systems live inside schedules so bevy's refresh path updates them on reload; call refresh_hotpatch manually on any system you cache outside a schedule.
  3. If stale pointers recur for scheduled systems, capture the sequence (patch timing vs. run timing) and report it upstream.
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: Applying a subsecond hot patch and then running a system whose cached pointer went stale because the refresh did not reach it; systems cached outside schedules missing their refresh_hotpatch call after reload.

Common situations: Hot-reload workflows that patch while systems are mid-execution or paused; tooling that reloads in a different order than bevy expects; long-running sessions accumulating partial patches.

Related errors


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