firecracker-microvm/firecracker · error
Device is not initialized
Error message
Device is not initialized
What it means
Panic from `expect("Device is not initialized")` in `Vsock::signal_used_queue` (src/vmm/src/devices/virtio/vsock/device.rs:141). `self.device_state.active_state()` returns `Some` only after the guest virtio driver has activated the device ( FEATURES_OK/DRIVER_OK handshake completed and the device moved to Activated). If any code path signals the used queue before activation, `active_state()` is None and the process aborts.
Source
Thrown at src/vmm/src/devices/virtio/vsock/device.rs:139
Self::with_queues(cid, backend, queues)
}
/// Retrieve the cid associated with this vsock device.
pub fn cid(&self) -> u64 {
self.cid
}
/// Access the backend behind the device.
pub fn backend(&self) -> &B {
&self.backend
}
/// Signal the guest driver that we've used some virtio buffers that it had previously made
/// available.
pub fn signal_used_queue(&self, qidx: usize) -> Result<(), DeviceError> {
self.device_state
.active_state()
.expect("Device is not initialized")
.interrupt
.trigger(VirtioInterruptType::Queue(qidx.try_into().unwrap_or_else(
|_| panic!("vsock: invalid queue index: {qidx}"),
)))
.map_err(DeviceError::FailedSignalingIrq)
}
/// Signal the guest which queues are ready to be consumed
pub fn signal_used_queues(&self, used_queues: &[u16]) -> Result<(), DeviceError> {
self.device_state
.active_state()
.expect("Device is not initialized")
.interrupt
.trigger_queues(used_queues)
.map_err(DeviceError::FailedSignalingIrq)
}
/// Walk the driver-provided RX queue buffers and attempt to fill them up with any data that weView on GitHub (pinned to 81b38b9dad)
Solutions
- Make sure the vsock backend event handler is only registered/started after the device receives DRIVER_OK (check `device_state.active_state().is_some()` before signaling)
- If restoring from a snapshot, verify the restore path calls `activate()` on the vsock device before resuming queue/event processing
- In library code, replace the `expect` with a graceful branch: `match self.device_state.active_state() { Some(s) => s.interrupt.trigger(..), None => { warn!(...); Ok(()) } }`
- If you drive the device from tests, activate it with a mock interrupt/queue pair first
Example fix
// before
self.device_state
.active_state()
.expect("Device is not initialized")
.interrupt
.trigger(VirtioInterruptType::Queue(qidx.try_into().unwrap_or_else(|_| panic!("vsock: invalid queue index: {qidx}"))))
.map_err(DeviceError::FailedSignalingIrq)
// after
if let Some(state) = self.device_state.active_state() {
state.interrupt
.trigger(VirtioInterruptType::Queue(qidx as u16))
.map_err(DeviceError::FailedSignalingIrq)
} else {
warn!("vsock: signal_used_queue before activation (qidx {qidx})");
Ok(())
} Defensive patterns
Strategy: validation
Validate before calling
// Only let the backend notify queues once the guest driver activated the device
if vsock.device_state().active_state().is_some() {
vsock.signal_used_queue(qidx)?;
} else {
warn!("vsock not activated; deferring queue signal");
} Type guard
fn is_vsock_activated(dev: &Vsock<impl VsockBackend>) -> bool {
dev.device_state().active_state().is_some()
} Try / catch
// Panics cannot be caught with Result; as a last resort isolate third-party threads:
let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| vsock.signal_used_queue(0)));
if r.is_err() { /* device not initialized or irq failure: restart device */ } Prevention
- Start vsock backend event processing only after the virtio DRIVER_OK activation handshake
- On snapshot restore, call activate() before re-registering queue event fds
- Confirm the guest kernel actually loads a virtio-vsock driver before relying on host->guest pushes
When it happens
Trigger: Calling `signal_used_queue(qidx)` (or the backend doing so indirectly) before the guest driver finished the virtio activation handshake: e.g. a host-side vsock peer connects and pushes data while the device is still in `Inactive`/`Created` state, or during snapshot-restore before `activate()` has run.
Common situations: Guest boots a kernel without a virtio-vsock driver (device never activates) while the host backend already delivers RX data; restoring from a snapshot where the backend/event handler threads start before the device is re-activated; tests that instantiate the device and drive queues directly without an activate step.
Related errors
- vsock: Could not trigger device interrupt
- GDB requires KVM
- Error getting initial gdb event
- Error converting cpu id to Tid
- GDB requires KVM
AI-assisted analysis of firecracker-microvm/firecracker@81b38b9dad (2026-08-19).
Data as JSON: /api/errors/e7fe63c5b518b10a.
Report an issue: GitHub.