firecracker-microvm/firecracker · error
TimerFd read failed
Error message
TimerFd read failed: {err:#} What it means
Reading the underlying timerfd file descriptor inside TimerFd::read failed with an I/O error other than EAGAIN/WouldBlock (which is normally swallowed and reported as 0 expirations, since the fd is opened NONBLOCK). This means the kernel refused or failed the read — typically because the fd is invalid/closed, or an unexpected OS-level condition occurred — so the number of expirations could not be retrieved. It fires as a panic at src/utils/src/time.rs:299 whenever file.read() on the real timerfd returns any error other than WouldBlock.
Solutions
- Check that the timerfd was created successfully and not closed before read.
- Handle EAGAIN on non-blocking timerfd reads and re-arm the timer correctly.
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at src/utils/src/time.rs:252 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of firecracker-microvm/firecracker@23b09b943f (2026-09-19).
Data as JSON: /api/errors/33da26fcb90905a1.
Report an issue: GitHub.
Appendix: source
Thrown at src/utils/src/time.rs:299
std::io::Error::last_os_error()
);
}
/// Read the value from the timer. Since a real timer is always created with the NONBLOCK
/// flag, this function does not block and returns `0` if the timer has not fired. For a mock
/// timer it returns the number of expirations that have occurred (per the virtual clock)
/// since the previous read.
pub fn read(&mut self) -> u64 {
let file = match self {
TimerFd::Real(file) => file,
#[cfg(any(test, feature = "test-utils"))]
TimerFd::Mock(mock) => return mock.read(),
};
let mut buf = [0u8; size_of::<u64>()];
match file.read(buf.as_mut_slice()) {
Ok(_) => u64::from_ne_bytes(buf),
Err(inner) if inner.kind() == ErrorKind::WouldBlock => 0,
Err(err) => panic!("TimerFd read failed: {err:#}"),
}
}
/// Tell if the timer is currently armed.
pub fn is_armed(&self) -> bool {
let file = match self {
TimerFd::Real(file) => file,
#[cfg(any(test, feature = "test-utils"))]
TimerFd::Mock(mock) => return mock.is_armed(),
};
// SAFETY: Zero init of a PDO type.
let mut spec: libc::itimerspec = unsafe { std::mem::zeroed() };
// SAFETY: Safe because timerfd_gettime is trusted to only modify `spec`.
let ret = unsafe { libc::timerfd_gettime(file.as_raw_fd(), &mut spec) };
assert!(
0 <= ret,
"TimerFd arm failed: {:#}",
std::io::Error::last_os_error()View on GitHub (pinned to 23b09b943f)