QEMU: The Ten Most Common Problems and How to Fix Them
Covers qemu-system on Linux, BSD, and Windows hosts, both standalone invocation and libvirt/virt-manager, ordered roughly by how often each problem comes up.
1. Could not access KVM kernel module: Permission denied
Symptom. QEMU or libvirt aborts at startup:
Could not access KVM kernel module: Permission denied
qemu-system-x86_64: failed to initialize KVM: Permission denied
Cause. The user running QEMU cannot open /dev/kvm. The correct state is mode 0660, owner root:kvm, with the user a member of the kvm group. The No such file or directory variant means the kvm_intel or kvm_amd module is not loaded — usually because VT-x or AMD-V (SVM) is disabled in firmware.
Fix.
ls -l /dev/kvm # expect: crw-rw---- root kvm
sudo usermod -aG kvm "$USER" # then log out and back in — group changes
# do not apply to existing sessions
lsmod | grep kvm # if empty: modprobe kvm_intel (or kvm_amd);
# if that fails, enable VT-x/SVM in BIOS/UEFI
Two less obvious variants:
- Libvirt configured with a numeric group ID: if
/etc/libvirt/qemu.confcontains something likegroup = "78", change it togroup = "kvm". Numeric mappings broke when systemd 234 started assigning thekvmgroup a dynamic GID; the group name always resolves correctly. - A
kvmgroup created outside the system GID range: udev then fails to resolve the group and/dev/kvmfalls back toroot:root 0600. Comparegetent group kvmagainstSYS_GID_MAXin/etc/login.defsand recreate the group inside the system range.
chmod 666 /dev/kvm also “works”, but it hands every local user hypervisor access; use the group instead.
2. Guest is unusably slow
Symptom. Boot takes minutes, the host CPU is pegged, and the same image runs fine in other hypervisors.
Cause. By default qemu-system-* runs in pure software emulation (TCG) with a generic CPU model, one vCPU, 128 MiB of RAM, and emulated legacy devices (IDE disk, e1000/rtl8139 NIC). None of these defaults suit a modern guest.
Fix. Enable hardware acceleration and paravirtual devices:
qemu-system-x86_64 \
-enable-kvm -cpu host -smp 4 -m 4G \
-drive file=disk.qcow2,if=virtio,cache=none,aio=native \
-nic user,model=virtio-net-pci \
...
-enable-kvm(equivalently-accel kvm) is the critical flag; without it nothing else matters. On macOS hosts the equivalent is-accel hvf, on Windows-accel whpx.-cpu hostpasses the host CPU features through instead of the generic default model.- virtio disk and NIC need guest drivers — built into Linux, a separate install on Windows (see problem 3).
- When disk I/O specifically is the bottleneck, use
cache=none,aio=native(libvirt:<driver name='qemu' type='...' cache='none' io='native'/>).
Verify acceleration is actually active from the QEMU monitor: info kvm must report kvm support: enabled.
3. Windows installer: “No drives were found” on a virtio disk
Symptom. Windows Setup reaches the disk-selection screen and lists no disks when the VM disk is attached as virtio (if=virtio, virtio-blk, or virtio-scsi).
Cause. Windows ships no virtio storage driver. The disk is present; the installer just cannot see it. This is expected behaviour, not a broken VM.
Fix.
- Download the
virtio-win.isodriver image (the Fedora project builds the canonical one for the upstream virtio-win drivers). - Attach it as a second CD-ROM alongside the Windows install ISO.
- At the disk screen: Load driver → browse the virtio ISO →
viostor(virtio-blk) orvioscsi(virtio-scsi) for your Windows version. The disk appears; continue setup. - After installation, load
netkvmfrom the same ISO for the virtio NIC, or run the bundled installer for the full driver set.
Alternative when the ISO route is inconvenient: install Windows on a SATA or IDE disk, install the virtio drivers inside Windows (attaching a small dummy virtio disk forces the driver to bind), then switch the boot disk to virtio.
4. Mouse cursor offset, double cursor, or grabbed pointer
Symptom. The guest cursor drifts away from the host cursor, two cursors render, or the pointer must be captured and released with a hotkey. Misalignment often worsens toward one corner of the window.
Cause. The default emulated pointing device is a PS/2 mouse, which reports relative motion. Host and guest disagree about pointer acceleration, so positions desynchronise.
Fix. Emulate an absolute-coordinate tablet instead:
-usb -device usb-tablet # modern syntax
# legacy equivalent: -usbdevice tablet
With absolute coordinates QEMU reports the exact pointer position without grabbing the mouse. virt-manager configures an equivalent tablet input by default, and under SPICE the guest agent provides the same client-mouse behaviour.
Residual cases that reproduce even with usb-tablet: the GTK display under HiDPI fractional scaling mis-scales tablet coordinates (reported against QEMU 7.2), and -display sdl,gl=on has a coordinate offset (reported against QEMU 9.0). Both are display-frontend bugs rather than configuration errors; work around them with a different display backend (GTK without scaling, SPICE, or VNC).
5. Networking “doesn’t work”: guest can’t ping out, host can’t reach guest
Symptom. With the default network setup the guest gets an address (10.0.2.15) and web traffic works, but ping fails inside the guest, and nothing on the host can connect to services in the guest.
Cause. Both behaviours are properties of the default SLIRP user-mode backend, not misconfiguration. It is a NAT stack inside QEMU (gateway and DNS at 10.0.2.2–10.0.2.3); ICMP is generally not passed, so ping is the wrong connectivity test, and inbound connections are blocked by design unless explicitly forwarded.
Fix.
- Test connectivity with TCP (
curl,ssh), notping. - Forward ports for inbound access:
-netdev user,id=n0,hostfwd=tcp::2222-:22 -device virtio-net-pci,netdev=n0
# then from the host: ssh -p 2222 user@localhost
hostfwd must be declared at launch, and it binds IPv4 only — connect to 127.0.0.1, not ::1.
- On Linux hosts, guest-side ping through SLIRP can be enabled by widening the unprivileged-ICMP range with the
net.ipv4.ping_group_rangesysctl. - If the guest must be a first-class network peer (inbound, ICMP, discovery), user mode is the wrong tool: switch to a TAP + bridge backend, or to
passt, a faster and more secure SLIRP replacement that also handles ICMP. Three integration levels, by version: QEMU 7.2 added-netdev stream, which connects to an externally started passt daemon; libvirt 9.0 added<backend type='passt'/>on auser-type interface; QEMU 10.1 added a native-netdev passt/-nic passtbackend that launches the daemon itself.
6. GPU passthrough: NVIDIA “Error 43” in the Windows guest
Symptom. A passed-through GeForce card shows in Windows Device Manager as Code 43: Windows has stopped this device, and the driver refuses to initialise.
Cause. GeForce drivers before the R465 branch — first public release 465.89, March 2021 — deliberately failed when they detected a hypervisor. From 465.89 onward the check is gone. Error 43 is also a generic driver failure, so on current drivers a remaining 43 usually points at ROM, reset, or IOMMU problems rather than hypervisor detection.
Fix.
- First: update the guest driver to 465.89 or newer. For many setups nothing else is needed.
- If the check still trips (pinned old driver, older stacks), hide the hypervisor:
libvirt XML:
<features>
<hyperv>
<vendor_id state='on' value='0123456789ab'/> <!-- any 12-char string -->
</hyperv>
<kvm>
<hidden state='on'/>
</kvm>
<ioapic driver='kvm'/> <!-- needed with QEMU >= 4.0 on Q35 -->
</features>
Plain QEMU:
-cpu host,kvm=off,hv_vendor_id=0123456789ab \
-machine type=q35,kernel_irqchip=on
On Proxmox, cpu: host,hidden=1 with the OS type set to Windows applies the equivalent automatically.
- Still 43 after both? Investigate the non-detection causes: dump and pass a clean vBIOS ROM, check IOMMU grouping and vfio-pci binding, and rule out known-bad platform firmware (on ASUS Prime X370/X470/X570-Pro boards, the early Ryzen-3000-support BIOS builds 4602 through 5220 break passthrough with
Unknown PCI header type '127'; builds up to 4406 and from 5406 onward work).
7. Disk image resized, guest still shows the old size
Symptom. qemu-img resize disk.qcow2 +20G succeeds, but the guest filesystem is still full. The inverse confusion also comes up: the guest sees the new size while the file on the host stays small — qcow2 is thin-provisioned and allocates on write.
Cause. qemu-img resize changes only the virtual block device. The partition table and filesystem inside it are guest structures and must be grown separately.
Fix. With the VM shut down:
qemu-img resize disk.qcow2 +20G
Then grow the partition and filesystem:
- Linux guest, online:
growpart /dev/vda 2(cloud-utils) orparted, thenresize2fs /dev/vda2(ext4) orxfs_growfs /(XFS). - Windows guest: Disk Management → right-click the volume → Extend Volume.
- Offline, host-side:
virt-resize --expand /dev/sda2 old.qcow2 new.qcow2(guestfs-tools) writes an expanded copy in one step.
Constraints:
qemu-imgrefuses to resize an image with internal snapshots — delete them first (qemu-img snapshot -d).- Shrinking is destructive unless the filesystem and partition are shrunk first inside the guest; only then
qemu-img resize --shrink. Take a backup copy before any resize — it is a one-linecp.
8. gtk initialization failed on servers, SSH sessions, WSL, containers
Symptom.
gtk initialization failed
sometimes preceded by Unable to init server: Could not connect: Connection refused or Authorization required, but no authorization protocol specified.
Cause. QEMU’s default display frontend is a GTK window; with no reachable display server (headless machine, plain SSH, WSL, a container) GTK cannot start. The Authorization required variant is X11 authorisation: running QEMU under sudo or doas drops XAUTHORITY and DISPLAY.
Fix. Pick the output you actually want:
-nographic # no window; serial console + monitor on the
# current terminal (multiplexed; C-a h for help)
-display none -vnc :0 # headless, graphics reachable via VNC on :5900
-display none -serial mon:stdio # headless, explicit serial-on-stdio
For the X-auth variant, run QEMU as your own user — KVM only needs the group membership from problem 1, not root — or preserve DISPLAY and XAUTHORITY across the privilege change.
9. Guest clock wrong by a fixed offset (Windows and legacy-OS guests)
Symptom. Windows, classic Mac OS, or another legacy guest shows a time offset from the host by exactly the timezone difference, and corrections do not survive a reboot.
Cause. QEMU’s emulated RTC defaults to UTC. Windows and most legacy operating systems interpret the hardware clock as local time, so the guest reads UTC and displays it as local.
Fix. One of:
-rtc base=localtime,clock=host # QEMU command line
<clock offset='localtime'/> <!-- libvirt -->
or, guest-side on Windows, declare the RTC to be UTC:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
"RealTimeIsUniversal"=dword:00000001
Distinguish this from other clock problems: a fixed timezone-sized offset is the RTC-base issue above; a clock that jumps to arbitrary times points at broken timekeeping (usually NTP) on the host; steady drift under load is what -rtc ...,driftfix=slew and the Hyper-V enlightenment hv_time address.
10. Host↔guest clipboard doesn’t work
Symptom. Copy and paste between host and guest does nothing, or works in one direction only.
Cause. Clipboard sharing is not built into the VM; it is an agent protocol with three links, and any missing link breaks it silently:
- a virtio-serial channel named
com.redhat.spice.0in the VM configuration, - the agent running in the guest —
spice-vdagenton Linux,vdagent.exe/vdservicefrom the SPICE guest tools on Windows, - a host side that speaks the protocol — a SPICE client, or QEMU’s built-in
qemu-vdagentchardev, introduced in QEMU 6.1 (August 2021) together with clipboard support in the GTK and VNC displays.
Fix. Plain QEMU 6.1 or newer, GTK or VNC display:
-device virtio-serial-pci \
-chardev qemu-vdagent,id=vd0,name=vdagent,clipboard=on \
-device virtserialport,chardev=vd0,name=com.redhat.spice.0
In virt-manager: Add Hardware → Channel → keep the name com.redhat.spice.0 (SPICE setups usually add it automatically). Then verify each link:
# Linux guest — channel present?
ls -l /dev/virtio-ports/ # must list com.redhat.spice.0
# Linux guest — agent running?
systemctl enable --now spice-vdagentd
On Windows guests, check that vdagent.exe is actually running; it failing to autostart after login is a common cause of one-directional paste. Over VNC, two extra conditions apply: the VNC client must implement clipboard exchange and have it enabled (support varies between viewers), and the shared clipboard does not survive live migration — restarting the agent in the guest (spice-vdagent, or the vdservice service on Windows) brings it back. On anything older than QEMU 6.1 there is no qemu-vdagent and no GTK/VNC clipboard at all; the only path is a full SPICE setup with a SPICE client.
