#2056·iii

macOS libkrun: RecvError / PSCI SystemOff when virtiofs share contains filenames with < >

Author: pwflintCreated Aug 13, 2026Updated Aug 13, 2026

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: RecvError

That 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_vmm 0.1.16 (libkrun / HVF)
  • Isolation: III_ISOLATION=libkrun, overlay rootfs (erofs lower + 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 RecvError on fc_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

  1. iii worker start <worker>Booting VM (2 vCPUs, 2048 MiB RAM)...fc_vcpu 1 RecvError. Worker returns to stopped. Guest stdout.log is empty.
  2. With MSB_KRUN_BOOT_TRACE=1 and 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.

  1. 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 directoryPSCI SystemOff / RecvError.
    • Worker B with those files moved aside (or templates dir removed) → boots, iii-init overlay message, npm install, worker registers.
    • Worker B with Worker A’s directory as --mount …:/mnt/host-srcboots.

So the failure tracks virtiofs readdir of < > names at share root, not TypeScript, overlay size, or concurrent VMs.

Steps to reproduce

  1. Local TypeScript worker with iii.worker.yaml runtime.language: typescript, overlay sandbox.
  2. Put a file named e.g. 0. <CLIENT> Lead Note.md inside the worker directory that is virtiofs-mounted as /mnt/host-src (not only behind a symlink outside the share).
  3. iii worker start <name> (or iii-worker __vm-boot with --mount ./that-dir:/mnt/host-src --vcpus 2).
  4. Observe RecvError on fc_vcpu 1. Repeat with --vcpus 1 and MSB_KRUN_BOOT_TRACE=1 to 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

  1. virtiofs/libkrun: tolerate or escape < > in host filenames, or fail start with the offending path.
  2. Do not unwrap() RecvError on the secondary vCPU boot channel — report vCPU 0’s PSCI SystemOff / console instead.
  3. 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.