bevyengine/bevy · critical
An elapsed time getter has not been provided to `Instant`. P
Error message
An elapsed time getter has not been provided to `Instant`. Please use `Instant::set_elapsed(...)` before calling `Instant::now()`
What it means
bevy_platform's fallback `Instant::now` reads a per-architecture monotonic counter via `unset_getter` (crates/bevy_platform/src/time/fallback.rs:151): `rdtsc` on x86/x86_64, `cntvct_el0` on aarch64. On every other architecture the `_` arm panics with this message — the only supported path there is to install a platform-specific elapsed-time getter with `Instant::set_elapsed(...)` before the first `now()` call.
Source
Thrown at crates/bevy_platform/src/time/fallback.rs:177
}
#[cfg(target_arch = "x86_64")] => {
// SAFETY: standard technique for getting a nanosecond counter on x86_64
let nanos = unsafe {
core::arch::x86_64::_rdtsc()
};
Duration::from_nanos(nanos)
}
#[cfg(target_arch = "aarch64")] => {
// SAFETY: standard technique for getting a nanosecond counter of aarch64
let nanos = unsafe {
let mut ticks: u64;
core::arch::asm!("mrs {}, cntvct_el0", out(reg) ticks);
ticks
};
Duration::from_nanos(nanos)
}
_ => {
panic!("An elapsed time getter has not been provided to `Instant`. Please use `Instant::set_elapsed(...)` before calling `Instant::now()`")
}
}
}
View on GitHub (pinned to 396ca72708)
Solutions
- Before any time use, register a monotonic getter: `Instant::set_elapsed(|| read_cycle_counter_as_duration())`
- Prefer enabling a real time source for the target (std `Instant` or the web time feature) instead of the fallback
- If the platform has no counter, build without the code paths that call `Instant::now()`
Example fix
// before: riscv no_std target, first Instant::now() panics
// after: install a cycle-counter-based getter at startup
Instant::set_elapsed(|| {
let ticks: u64;
unsafe { core::arch::asm!("csrr {0}, cycle", out(reg) ticks) };
Duration::from_nanos(ticks / CLOCKS_PER_SEC_NANO) // scaled to nanos
});
let now = Instant::now(); Defensive patterns
Strategy: validation
Validate before calling
// compile-time guard for fallback-time targets
#[cfg(all(
not(target_arch = "x86"),
not(target_arch = "x86_64"),
not(target_arch = "aarch64"),
not(feature = "web")
))]
compile_error!("bevy_platform fallback Instant needs Instant::set_elapsed on this arch");
// runtime: install the getter before anything calls now()
Instant::set_elapsed(read_monotonic_counter); Prevention
- Call Instant::set_elapsed as the first statement of main on no_std targets without built-in counters
- Cross-compile CI (`cargo build --target riscv64imac-unknown-none-elf`) to catch unsupported-arch panics early
- Prefer the std or web time feature whenever the target allows it
When it happens
Trigger: Compiling with the fallback time implementation (no_std, web feature off, std time unavailable) for a target that is not x86, x86_64, or aarch64 — e.g. riscv32/riscv64, 32-bit arm, powerpc — and touching `Instant::now()`/`Instant::update()` (Bevy's Time plugin does this at startup), without calling `Instant::set_elapsed` first.
Common situations: Embedded/no_std Bevy ports or crates depending on bevy_platform built for exotic targets; CI cross-compile checks that actually run tests on riscv/arm bare-metal; switching a no_std project from a supported to an unsupported architecture.
Related errors
- overflow when adding duration to instant
- overflow when subtracting duration from instant
- The TimeSender channel should always be empty during render.
- Cannot call `ReflectComponent::reflect_mut` on component {na
- Cannot call `ReflectComponent::reflect_unchecked_mut` on com
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/0a77bb483913636b.
Report an issue: GitHub.