{"record":{"id":"8dafaea5201c12c2","repo":"firecracker-microvm/firecracker","slug":"vhostuserblock-does-not-support-snapshotting-yet","errorCode":null,"errorMessage":"VhostUserBlock does not support snapshotting yet","messagePattern":"VhostUserBlock does not support snapshotting yet","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/vmm/src/devices/virtio/block/vhost_user/device.rs","lineNumber":243,"sourceCode":"            queues,\n            queue_evts,\n            device_state,\n\n            id: config.drive_id,\n            partuuid: config.partuuid,\n            cache_type: config.cache_type,\n            read_only,\n            root_device: config.is_root_device,\n\n            vu_handle,\n            vu_acked_protocol_features: acked_protocol_features,\n            metrics,\n        })\n    }\n\n    /// Prepare device for being snapshotted.\n    pub fn prepare_save(&mut self) {\n        unimplemented!(\"VhostUserBlock does not support snapshotting yet\");\n    }\n\n    pub fn config(&self) -> VhostUserBlockConfig {\n        VhostUserBlockConfig {\n            drive_id: self.id.clone(),\n            partuuid: self.partuuid.clone(),\n            is_root_device: self.root_device,\n            cache_type: self.cache_type,\n            socket: self.vu_handle.socket_path.clone(),\n        }\n    }\n\n    pub fn config_update(&mut self) -> Result<(), VhostUserBlockError> {\n        let start_time = get_time_us(ClockType::Monotonic);\n        let interrupt = self\n            .device_state\n            .active_state()\n            .expect(\"Device is not initialized\")","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/firecracker-microvm/firecracker/blob/ea50487ec11602100b90ed63f85fe00bd30fbde8/src/vmm/src/devices/virtio/block/vhost_user/device.rs#L225-L261","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before (microVM config uses a vhost-user block backend, then snapshot)\ncurl --unix-socket fc.sock -X PUT http://localhost/snapshot/create -d '{\"snapshot_path\": \"snap.mem\", \"mem_file_path\": \"snap.mem\"}'\n# firecracker process panics: VhostUserBlock does not support snapshotting yet\n\n# after (use virtio-block for VMs that will be snapshotted)\ncurl --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}'","handlingStrategy":"validation","validationCode":"// Before issuing CreateSnapshot, inspect the VM config for vhost-user blocks.\n// vhost-user block drives are configured with a `socket` field; virtio-block uses path_on_host.\nfn has_vhost_user_block(cfg: &FirecrackerVmConfig) -> bool {\n    cfg.drives\n        .iter()\n        .any(|d| d.socket.as_ref().is_some_and(|s| !s.is_empty()))\n}\n\nif has_vhost_user_block(&vm_config) {\n    return Err(anyhow::anyhow!(\n        \"refusing to snapshot: vhost-user block devices do not support snapshotting (panics in prepare_save)\"\n    ));\n}\napi.create_snapshot(req).await?;","typeGuard":"fn snapshot_safe_drive(d: &BlockDeviceConfig) -> bool {\n    // virtio-block drives (path_on_host, no socket) are snapshot-safe;\n    // socket-backed vhost-user drives are not.\n    d.socket.is_none() && d.path_on_host.is_some()\n}","tryCatchPattern":"// unimplemented!() panics the VMM thread, so catch_unwind is the only in-process option —\n// prefer the config validation above. At the supervisor level, treat firecracker\n// process death + \"not implemented\" in logs after CreateSnapshot as this defect.\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    vmm.snapshot_create(path)\n}));\nif result.is_err() {\n    tracing::error!(\"snapshot failed: vhost-user block prepare_save is unimplemented\");\n}","preventionTips":["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."],"tags":["rust","firecracker","vhost-user","snapshot","panic","virtio-block"],"backgroundTag":null,"analyzedSha":"ea50487ec11602100b90ed63f85fe00bd30fbde8","analyzedAt":"2026-08-16T11:52:35.093Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}