iced-rs/iced · error
Hot function is stale
Error message
Hot function is stale
What it means
`hot::call` wraps your function in an FnOnce closure consumed exactly once via `f.take().expect("Hot function is stale")`. The panic means the subsecond/cargo-hot runtime invoked the wrapper closure a second time after the FnOnce was already taken — stale code for the function ran again after (or during) a hotpatch swap, violating the run-once invariant.
Source
Thrown at debug/src/lib.rs:445
if HOT_FUNCTIONS.get().is_none() {
HOT_FUNCTIONS
.set(std::mem::take(
&mut HOT_FUNCTIONS_PENDING.lock().expect("Lock hot functions"),
))
.expect("Set hot functions");
}
IS_STALE.store(false, atomic::Ordering::Relaxed);
}));
}
pub fn call<O>(f: impl FnOnce() -> O) -> O {
let mut f = Some(f);
// The `move` here is important. Hotpatching will not work
// otherwise.
let mut f = cargo_hot::subsecond::HotFn::current(move || {
f.take().expect("Hot function is stale")()
});
let address = f.ptr_address().0;
if let Some(hot_functions) = HOT_FUNCTIONS.get() {
if hot_functions.contains(&address) {
IS_STALE.store(true, atomic::Ordering::Relaxed);
}
} else {
let _ = HOT_FUNCTIONS_PENDING
.lock()
.expect("Lock hot functions")
.insert(address);
}
f.call(())
}
View on GitHub (pinned to 2cffa99b39)
Solutions
- Make hot-instrumented entry points non-reentrant (hoist recursion out of functions wrapped by hot::call)
- Ensure only one subsecond handler/init path is registered (duplicate handlers re-dispatch stale frames)
- Align cargo-hot/subsecond versions with the iced debug crate and restart the hot-reload session
- If reproducible with hotpatching disabled, or deterministic on one input, report upstream to iced/cargo-hot with the backtrace
Defensive patterns
Strategy: validation
Try / catch
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| hot::call(work)));
if result.is_err() {
// stale-frame invariant broken: end the hot-reload session, keep the process
log::error!("hot function executed twice — restart the hot-reload session");
} Prevention
- Keep functions wrapped by hot::call non-reentrant; hoist recursion and mutual recursion out
- Do not register multiple subsecond handlers — re-dispatch is the main way a frame runs twice
- Restart the hot-reload session after any panic or patch anomaly instead of continuing on stale frames
- Match cargo-hot/subsecond versions with the iced debug crate you build against
When it happens
Trigger: Re-entrant execution of a hot-instrumented function while a patch is being applied; a hotpatched function reached from multiple dispatch paths where cargo-hot swaps it mid-flight; subsecond replaying a frame after a patch.
Common situations: Editing recursive or mutually recursive functions under iced hot reload; long-running frames where the patched function is on the stack when the patch lands; version mismatch between cargo-hot/subsecond and iced's debug crate.
Related errors
- Lock hot functions
- Set hot functions
- Encode input message
- Encode input message
- Write application metadata
AI-assisted analysis of iced-rs/iced@2cffa99b39 (2026-08-16).
Data as JSON: /api/errors/10cac6d603115e42.
Report an issue: GitHub.