firecracker-microvm/firecracker · critical
VhostUserBlock does not support snapshotting yet
Error message
VhostUserBlock does not support snapshotting yet
What it means
`VhostUserBlock::prepare_save` in src/vmm/src/devices/virtio/block/vhost_user/device.rs is a hard `unimplemented!()` stub: vhost-user block devices delegate the virtio data plane to an external process, and Firecracker has not implemented capturing that external device's state. When a snapshot request reaches the device-state collection phase, this macro panics and tears down the VMM thread — it is not a catchable API error.
Source
Thrown at src/vmm/src/devices/virtio/block/vhost_user/device.rs:243
queues,
queue_evts,
device_state,
id: config.drive_id,
partuuid: config.partuuid,
cache_type: config.cache_type,
read_only,
root_device: config.is_root_device,
vu_handle,
vu_acked_protocol_features: acked_protocol_features,
metrics,
})
}
/// Prepare device for being snapshotted.
pub fn prepare_save(&mut self) {
unimplemented!("VhostUserBlock does not support snapshotting yet");
}
pub fn config(&self) -> VhostUserBlockConfig {
VhostUserBlockConfig {
drive_id: self.id.clone(),
partuuid: self.partuuid.clone(),
is_root_device: self.root_device,
cache_type: self.cache_type,
socket: self.vu_handle.socket_path.clone(),
}
}
pub fn config_update(&mut self) -> Result<(), VhostUserBlockError> {
let start_time = get_time_us(ClockType::Monotonic);
let interrupt = self
.device_state
.active_state()
.expect("Device is not initialized")View on GitHub (pinned to ea50487ec1)
Solutions
- Do not snapshot microVMs that have a vhost-user block attached — replace it with a standard virtio-block drive (`virtio-block` / BlockDeviceConfig without a vhost-user socket) before CreateSnapshot.
- Detach the vhost-user block and re-attach it after restore: build the VM with virtio-block, snapshot, restore, then swap in the vhost-user backend post-restore if your orchestration supports re-configuration.
- Track/upgrade Firecracker versions where vhost-user block snapshotting lands; check the release notes for the device you use before relying on snapshots.
- In orchestrators, gate snapshot operations on the absence of vhost-user devices (see validation below) so the panic never fires.
Example fix
# before (microVM config uses a vhost-user block backend, then snapshot)
curl --unix-socket fc.sock -X PUT http://localhost/snapshot/create -d '{"snapshot_path": "snap.mem", "mem_file_path": "snap.mem"}'
# firecracker process panics: VhostUserBlock does not support snapshotting yet
# after (use virtio-block for VMs that will be snapshotted)
curl --unix-socket fc.sock -X PUT http://localhost/drives/snapshot_drive -H 'Content-Type: application/json' -d '{"drive_id": "snapshot_drive", "path_on_host": "/data/disk.ext4", "is_root_device": false, "is_read_only": false}' Defensive patterns
Strategy: validation
Validate before calling
// Before issuing CreateSnapshot, inspect the VM config for vhost-user blocks.
// vhost-user block drives are configured with a `socket` field; virtio-block uses path_on_host.
fn has_vhost_user_block(cfg: &FirecrackerVmConfig) -> bool {
cfg.drives
.iter()
.any(|d| d.socket.as_ref().is_some_and(|s| !s.is_empty()))
}
if has_vhost_user_block(&vm_config) {
return Err(anyhow::anyhow!(
"refusing to snapshot: vhost-user block devices do not support snapshotting (panics in prepare_save)"
));
}
api.create_snapshot(req).await?; Type guard
fn snapshot_safe_drive(d: &BlockDeviceConfig) -> bool {
// virtio-block drives (path_on_host, no socket) are snapshot-safe;
// socket-backed vhost-user drives are not.
d.socket.is_none() && d.path_on_host.is_some()
} Try / catch
// unimplemented!() panics the VMM thread, so catch_unwind is the only in-process option —
// prefer the config validation above. At the supervisor level, treat firecracker
// process death + "not implemented" in logs after CreateSnapshot as this defect.
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
vmm.snapshot_create(path)
}));
if result.is_err() {
tracing::error!("snapshot failed: vhost-user block prepare_save is unimplemented");
} Prevention
- Policy-gate snapshots: never send CreateSnapshot to a VM whose config contains socket-backed drives.
- Prefer virtio-block for any workload that may later need snapshot/restore or migration.
- Test the snapshot path of your exact device set in CI so unsupported combos fail in tests, not production.
- Track the Firecracker version's vhost-user snapshot support matrix before upgrading device backends.
When it happens
Trigger: Attaching a block device whose backend is a vhost-user socket (e.g. spawned via vhost-user-blk backend + `drive` config with `socket` in vhost-user variants of the block device) and then calling the Firecracker API `PUT /snapshot/create` (CreateSnapshot). The VMM iterates devices to prepare them for saving, hits the vhost-user block, and panics at device.rs:243. The same happens for snapshot load flows that call prepare-save paths.
Common situations: Teams adopting vhost-user-blk for out-of-process storage (e.g. SPDK or custom backends) who then try to use Firecracker's snapshot/restore (live migration, fast-scaling, VM templating beyond what vhost-user supports). Nothing in the API rejects the combination at request time, so the failure only appears at snapshot time as a firecracker process abort with 'internal error: not implemented' in logs.
Related errors
- VhostUserBlock does not support snapshotting yet
- No kernel found and --kernel was not provided.
- No rootfs found and --rootfs was not provided.
AI-assisted analysis of firecracker-microvm/firecracker@ea50487ec1 (2026-08-16).
Data as JSON: /api/errors/8dafaea5201c12c2.
Report an issue: GitHub.