> For the complete documentation index, see [llms.txt](https://docs.layeronecloud.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.layeronecloud.com/pve-microvm/known-issues.md).

# Known Issues

Source project: `pve-microvm` (migrated from `docs/known-issues.md`). Run commands from the code checkout and directory specified below, not from this documentation repository.

## systemd-networkd config matching (WORKAROUND in v0.1.21+) <a href="#systemd-networkd-config-matching-workaround-in-v0121" id="systemd-networkd-config-matching-workaround-in-v0121"></a>

systemd-networkd on Trixie doesn't match `.network` config files for eth0 after the initrd switch\_root. `networkctl status eth0` shows `Network File: n/a` despite correct file permissions and matching criteria.

**Root cause**: The initrd's devtmpfs doesn't generate udev events that networkd uses for link matching. The interface is UP with carrier but networkd never claims it.

**Workaround**: A `microvm-dhcp.service` runs `dhclient -4 eth0` at boot as a reliable fallback. DHCP works instantly via dhclient.

## Guest-agent port discovery (FIXED in v0.3.24) <a href="#guest-agent-port-discovery-fixed-in-v0324" id="guest-agent-port-discovery-fixed-in-v0324"></a>

The shipped kernel includes `CONFIG_VIRTIO_CONSOLE=y`, so the port itself is present, but two assumptions a normal PVE guest can make do not hold here.

The named device never appears. The initrd hand-off does not replay the udev event that creates `/dev/virtio-ports/org.qemu.guest_agent.0`, so that path does not exist at all — not merely late. The vendor `qemu-guest-agent.service` waits for it and stays inactive forever even though the driver and the raw port are working.

The port number is not fixed. `vport<bus>p<port>` is numbered in virtio probe order, so it moves with the device set on the command line. A Debian trixie guest on PVE 9.1.9 / QEMU 10.1.2 lands on `/dev/vport2p1`, not the `/dev/vport1p1` that earlier revisions of this document and of `pve-microvm-template` hardcoded. Any fixed number is a guess.

Older templates worked around the first problem with a separate `microvm-agent.service`. If the vendor unit later started too, both processes competed for the same port and the custom service restarted forever.

Current templates keep exactly one service named `qemu-guest-agent.service`. A microVM-specific replacement unit polls for up to 60 seconds, taking the named device if something did create it and otherwise the first `/dev/vport*p*` character device, runs the packaged `qemu-ga` binary against whichever it found, and uses `Restart=always` without depending on the named udev symlink.

For an existing Debian/Ubuntu guest, remove the legacy and vendor-device assumptions by copying the replacement unit from a newly generated template or create this equivalent unit with the correct `qemu-ga` path:

```ini
[Unit]
Description=QEMU Guest Agent for microVM
After=local-fs.target

[Service]
Type=simple
ExecStart=/bin/sh -c 'i=0; while test $i -lt 60; do for port in /dev/virtio-ports/org.qemu.guest_agent.0 /dev/vport*p*; do test -c "$port" && exec /usr/sbin/qemu-ga --method=virtio-serial --path="$port"; done; i=$((i + 1)); sleep 1; done; exit 1'
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

Then run:

```bash
systemctl disable --now microvm-agent.service 2>/dev/null || true
rm -f /etc/systemd/system/microvm-agent.service
rm -rf /etc/systemd/system/qemu-guest-agent.service.d
systemctl daemon-reload
systemctl enable --now qemu-guest-agent.service
```

Enterprise Linux commonly installs the binary as `/usr/bin/qemu-ga`; verify with `command -v qemu-ga` before writing the unit.

## Serial console <a href="#serial-console" id="serial-console"></a>

Uses a custom `microvm-console.service` with `agetty --autologin root` instead of the stock `serial-getty@ttyS0` which requires udev device events that devtmpfs from initrd doesn't generate.

## Serial buffering <a href="#serial-buffering" id="serial-buffering"></a>

QEMU's serial chardev socket doesn't buffer when no client is connected. Boot messages may be lost. Connect via `qm terminal` or the web UI Console.

## PCI: Fatal: No config space access function found <a href="#pci-fatal-no-config-space-access-function-found" id="pci-fatal-no-config-space-access-function-found"></a>

Harmless warning from the microvm boot. The guest kernel tries standard PCI config space probing before the PCIe ECAM from microvm is initialized. Does not affect device functionality — all virtio devices bind correctly.

## Cloud-init Perl warning (FIXED in qemu-server 9.1.8) <a href="#cloud-init-perl-warning-fixed-in-qemu-server-918" id="cloud-init-perl-warning-fixed-in-qemu-server-918"></a>

```
Use of uninitialized value in split at /usr/share/perl5/PVE/QemuServer/Cloudinit.pm line 115.
```

Harmless PVE warning when generating cloud-init ISO for microvms. Cloud-init data is injected correctly despite the warning.

**Fixed**: This warning is resolved in `qemu-server` 9.1.8+.

## HA relocate (not live) <a href="#ha-relocate-not-live" id="ha-relocate-not-live"></a>

HA relocate works but performs stop→migrate→start (not live migration). Expect 2-10 seconds of downtime during relocate depending on hardware.

## Cloud-init drive order (FIXED in v0.3.3) <a href="#cloud-init-drive-order-fixed-in-v033" id="cloud-init-drive-order-fixed-in-v033"></a>

On `qemu-server` < 9.1.8, the cloud-init ISO (`scsi1`) could appear as `/dev/vda` before the root disk, breaking `root=/dev/vda` in the kernel args.

**Root cause**: Three issues combined:

1. `PVE::QemuServer::Drive::valid_drive_names()` returns 0 items at runtime inside `config_to_command` on qemu-server 9.1.6
2. `is_microvm()` relied on `Machine::parse_machine()` which could fail on older qemu-server versions
3. Drive iteration order was not guaranteed

**Fix** (v0.3.3):

1. `is_microvm()` falls back to raw string match if parse fails
2. Drive loop iterates `keys %$conf` (not `valid_drive_names()`)
3. Sort guarantees scsi0 is always emitted first (`/dev/vda` = root)
4. Cloud-init ISO included as `/dev/vdb` (needed for config delivery)
5. Root filesystem labelled `microvm-root` for future LABEL= boot

Cloud-init does not move the root disk in current releases. Keep `root=/dev/vda`; the data disk is `/dev/vdb`.

## File-backed linked clone detected as raw (FIXED in v0.3.23) <a href="#file-backed-linked-clone-detected-as-raw-fixed-in-v0323" id="file-backed-linked-clone-detected-as-raw-fixed-in-v0323"></a>

Releases through v0.3.22 called a nonexistent `PVE::Storage::volume_format()` function. Because the call was inside `eval`, the failure was hidden and the command builder defaulted to raw. A file-backed qcow2 linked clone was then passed to QEMU as `format=raw` and failed to boot.

The command builder now reads the seventh value from `PVE::Storage::parse_volname()`, which is PVE's actual volume format metadata. Unknown formats and parser failures stop command generation instead of risking writes through the wrong block driver. Explicit drive formats still take priority, and RBD continues to use `format=rbd`.

## Docker containers fail: bpf\_prog\_query not implemented (FIXED in v0.3.9) <a href="#docker-containers-fail-bpf_prog_query-not-implemented-fixed-in-v039" id="docker-containers-fail-bpf_prog_query-not-implemented-fixed-in-v039"></a>

Docker's runc requires BPF cgroup device controller support:

```
bpf_prog_query(BPF_CGROUP_DEVICE) failed: function not implemented
```

**Root cause**: The microvm kernel overlay had `CONFIG_CGROUP_BPF=y` but not `CONFIG_BPF_SYSCALL=y`, so `CGROUP_BPF` was silently disabled by `make olddefconfig`.

**Fix** (v0.3.9): Added `CONFIG_BPF_SYSCALL`, `CONFIG_BPF_JIT`, `CONFIG_BPF_JIT_ALWAYS_ON` to the overlay. Requires kernel rebuild.

**Workaround**: Use the Debian stock kernel for Docker workloads:

```bash
# Inside the microvm, install the Debian kernel:
apt-get install -y linux-image-amd64

# On the host, extract and switch:
# (see virtualdsm/archivebox examples in the docs)
qm set <vmid> --args "-kernel /usr/share/pve-microvm/vmlinuz-docker ..."
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.layeronecloud.com/pve-microvm/known-issues.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
