macOS libkrun: RecvError / PSCI SystemOff when virtiofs share contains filenames with < >
Summary
On macOS with libkrun-managed TypeScript workers (iii 0.22.1), booting a worker whose host-src virtiofs share contains filenames with < / > (e.g. Obsidian templates 0. <CLIENT> Lead Note.md) causes the guest to PSCI SystemOff ~80ms after event_loop.start, with an empty guest console.
With the default 2 vCPUs, that surfaces as:
thread 'fc_vcpu 1' panicked at msb_krun_vmm-0.1.16/src/macos/vstate.rs:456:34:
called `Result::unwrap()` on an `Err` value: RecvErrorThat RecvError is a secondary panic: vCPU 1 is blocked on boot_receiver.recv() waiting for PSCI CPU_ON; vCPU 0 already shut down, so the sender is dropped.
This is not iii#2049 (stale __vm-boot / worker-manager-daemon accumulation, addressed in 0.19.3). Zombie count is 0–1 here. A sibling TypeScript worker on the same host, same base erofs (docker.io-iiidev-node-latest), same iii.worker.yaml shape, boots in a few seconds.
Environment
- OS: macOS Apple Silicon (darwin 24.x)
- iii / iii-worker: 0.22.1 (
~/.local/bin) - VMM:
msb_krun_vmm0.1.16 (libkrun / HVF) - Isolation:
III_ISOLATION=libkrun, overlay rootfs (erofslower +upper.ext4) - Workers: two local TypeScript workers; only the one whose virtiofs tree contains
<>names fails
Expected behavior
- Filenames that are legal on the macOS host (and common in Obsidian vaults) should not abort guest boot.
- If they cannot be represented in the guest/virtiofs, start should fail with a clear error naming the path — not
RecvErroronfc_vcpu 1. - With 1 vCPU, a guest that cannot boot should still log why (console / iii-init), not silent PSCI SystemOff + empty
stdout.log.
Actual behavior
iii worker start <worker>→Booting VM (2 vCPUs, 2048 MiB RAM)...→fc_vcpu 1RecvError. Worker returns tostopped. Gueststdout.logis empty.- With
MSB_KRUN_BOOT_TRACE=1and 1 vCPU (so vCPU 1 is not in the picture):
vcpus.started
event_loop.start
vCPU 0 PSCI
vCPU 0 PSCI
vCPU 0 received shutdown signal
using vcpu exit code: 0
Vmm is stopping.Console file remains 0 bytes. Exit code 0.
- A/B (same machine, same image, same ram/vcpus pattern):
- Worker A virtiofs root has a symlink
kb→ sibling tree that contains the<CLIENT>files → boots. - Worker B virtiofs root has those files as a real directory → PSCI SystemOff / RecvError.
- Worker B with those files moved aside (or templates dir removed) → boots,
iii-initoverlay message, npm install, worker registers. - Worker B with Worker A’s directory as
--mount …:/mnt/host-src→ boots.
- Worker A virtiofs root has a symlink
So the failure tracks virtiofs readdir of < > names at share root, not TypeScript, overlay size, or concurrent VMs.
Steps to reproduce
- Local TypeScript worker with
iii.worker.yamlruntime.language: typescript, overlay sandbox. - Put a file named e.g.
0. <CLIENT> Lead Note.mdinside the worker directory that is virtiofs-mounted as/mnt/host-src(not only behind a symlink outside the share). iii worker start <name>(oriii-worker __vm-bootwith--mount ./that-dir:/mnt/host-src --vcpus 2).- Observe RecvError on
fc_vcpu 1. Repeat with--vcpus 1andMSB_KRUN_BOOT_TRACE=1to see PSCI SystemOff and empty console.
Workarounds (consumer)
- Keep names with
<>out of the virtiofs share (e.g. rsync--exclude '*<*>*', or expose that tree only via a symlink from a sibling worker dir). - 1 vCPU avoids the RecvError message but the guest still SystemOff if the names are present.
Suggested fixes
- virtiofs/libkrun: tolerate or escape
<>in host filenames, or fail start with the offending path. - Do not
unwrap()RecvError on the secondary vCPU boot channel — report vCPU 0’s PSCI SystemOff / console instead. - Ensure virtio console is flushed on early SystemOff so iii-init/kernel messages are not lost.
Happy to retest a build or attach a longer MSB_KRUN_BOOT_TRACE log.
Source: iii-hq/iii