Skip to content

VirtualBox Windows 11 VM: AHCI Freeze on Boot/Setup, and a Separate Unattend ProductKey Trap

TL;DR

Building an unattended Windows 11 VM in VirtualBox (Windows host, EFI firmware, TPM 2.0) can hit two unrelated bugs that look like one:

  1. A genuine VirtualBox AHCI controller freeze — the VM hard-stalls (guest's own virtual clock stops advancing, not just quiet logs) right after an AHCI#0: Reset the HBA log line, at unpredictable points wherever there's a disk-write burst (initial Setup file-copy, or later during OOBE account/security-question writes).
  2. A missing <ProductKey> element in autounattend.xml that forces Setup to show the interactive "Enter product key" screen regardless of whether the answer file is being read correctly — easy to misdiagnose as "the unattended file isn't being detected at all."

Diagnosing them separately matters: fixing #2 does nothing for #1, and chasing #1 (e.g. by trying different storage controllers) can waste real time if #2 is what's actually blocking progress.

Symptom 1: The freeze/hang

  • VM appears to hang — screen static, no response to injected keystrokes (VBoxManage controlvm <vm> keyboardputscancode), VM state stays running in VBoxManage showvminfo.
  • VBox.log tail shows the guest's own timestamp stop advancing after a line like:
    AHCI#0: Reset the HBA
    VD#0: Cancelling all active requests
    
    Sometimes preceded by TM: Giving up catch-up attempt at a <N> ns lag — the hypervisor's Time Manager gave up trying to keep the guest's virtual clock in sync with wall-clock time.
  • The VDI file's size may stay static (no growth) if the freeze happens very early, or may have grown normally right up to the freeze point if it happens later (e.g., mid-OOBE).
  • Do not repeatedly hard-reset (VBoxManage controlvm <vm> reset) while this is happening if real disk writes are in flight. A reset genuinely recovers the VM (state goes back to running, boot proceeds), but resetting during an active write (e.g., the local-account/security-questions step of OOBE, which writes to the registry/SAM) can corrupt the install past repair — symptom: Your device ran into a problem and couldn't be repaired / Log file: C:\WINDOWS\System32\Logfiles\Srt\SrtTrail.txt on next boot, with no way to recover short of reinstalling.
  • A reset is safe when the freeze happens at a point with no in-flight writes (e.g., very early in Setup, or once you can confirm via VBox.log/VDI-size that nothing is actively being written) — but you can't always tell for certain, so treat every reset during this bug as a small risk, not a guaranteed-safe recovery.

Known workaround (community-confirmed, but ISO-dependent)

VirtualBox forum reports (e.g. AHCI Port Reset Without Clear Reason, ticket #15374) describe this exact class of bug and suggest switching the guest's storage controller away from SATA/AHCI (to SAS, or NVMe) as a workaround.

This only helps if the Windows Setup boot environment (boot.wim) actually has inbox drivers for the replacement controller. Tested on a Win11_25H2_English_x64_v2.iso (non-standard "_v2" filename, possibly a trimmed/modified build — official Microsoft ISOs may differ):

  • VBoxManage storagectl <vm> --name SAS --add sas --controller LSILogicSAS — Setup's "Select location to install Windows 11" screen showed zero disks, even though the disk was visibly present at the hypervisor/EFI level (LsiLogic#0: Guest issued CDB... in the log, valid INQUIRY responses).
  • VBoxManage storagectl <vm> --name NVMe --add pcie --controller NVMe — same result, zero disks, despite EFI's own NvmExpressDxe.efi loading fine and the log confirming the NVMe namespace (NVMe#0Ns0: disk, total number of blocks ...).
  • Reverting to SATA/IntelAhci — disk visible immediately, install proceeded normally (freeze notwithstanding).

Lesson: don't assume a community-suggested controller swap will work without checking the target ISO can actually see it — verify at the "select install location" screen (or watch VBox.log for Guest issued CDB traffic vs. a completely silent controller) before investing more time. If the controller shows zero disks, revert rather than trying a third controller type blind.

What actually got a full install through, on SATA

With the ProductKey bug (below) fixed so the install ran genuinely unattended start-to-finish, the same AHCI reset event still occurred once during file-copy — but this time the log kept producing entries afterward instead of going silent, and installation completed normally to a working desktop. Whether this means the freeze is reliably "survivable if you just wait" versus "got lucky this run" is not conclusively answered — treat any recurrence with caution (avoid resetting mid-write; consider just waiting longer before concluding it's truly stuck).

Symptom 2: "The unattended install isn't working" (Product Key prompt)

  • Windows Setup shows the interactive "Product key" screen ("The product key should be with the box the DVD came in...") even though autounattend.xml/autounattend.iso is correctly attached, correctly structured (single autounattend.xml at ISO root — verify with 7z l <iso> or isoinfo), and otherwise valid XML.
  • Easy to misread as "the answer file isn't being detected at all" — especially if you also have the AHCI freeze bug happening nearby, since the two symptoms compound (freeze during manual OOBE click-through after the false "unattended isn't working" conclusion led to abandoning automation).

Cause

autounattend.xml's <settings pass="windowsPE"><component name="Microsoft-Windows-Setup">...<UserData> block had <AcceptEula>, <FullName>, <Organization> — but no <ProductKey> element at all. Without it, Setup falls back to prompting interactively for a key, regardless of whether every other part of the answer file (disk wipe/partition via <DiskConfiguration>, edition selection via <InstallFrom><MetaData>, TPM/SecureBoot bypass via <RunSynchronous>) is being read and applied correctly.

Fix

Add a <ProductKey> block with a generic Microsoft-published KMS client setup key matching the target edition (these are public, non-secret placeholders — not real licenses — published by Microsoft specifically for unattended/volume-license-style installs) and set WillShowUI to Never:

<UserData>
  <AcceptEula>true</AcceptEula>
  <FullName>Marcus Summers</FullName>
  <Organization>MajorLab</Organization>
  <ProductKey>
    <Key>W269N-WFGWX-YVC9B-4J6C9-T83GX</Key>
    <WillShowUI>Never</WillShowUI>
  </ProductKey>
</UserData>

(W269N-WFGWX-YVC9B-4J6C9-T83GX is the public Windows 11 Pro generic KMS client key — swap for the matching key if targeting a different edition.)

After editing, rebuild the ISO (don't just edit the XML and reattach the old ISO — Windows Setup reads from the ISO, not the source file):

mkdir -p /tmp/autounattend-iso
cp autounattend.xml /tmp/autounattend-iso/
genisoimage -o autounattend.iso -V "AUTOUNATTEND" -J -R /tmp/autounattend-iso/

Verify the fix by watching for the Product Key screen — with it correctly present, Setup should sail straight through to "We're getting a few things ready" / disk partitioning without pausing.

Diagnostic techniques used

  • Screenshots via VBoxManage controlvm <vm> screenshotpng <path> — works even when the VM is otherwise unresponsive to input, since it reads the framebuffer directly. Essential for telling "genuinely frozen" apart from "waiting on a screen you haven't seen yet" (e.g. a boot-device prompt, or Setup quietly progressing).
  • Injected keypresses via VBoxManage controlvm <vm> keyboardputscancode <make> <break> — e.g. Enter is 1c 9c, Tab is 0f 8f. Useful both for automating "press any key to boot from CD" prompts and as a diagnostic: if an injected keypress produces zero change in a follow-up screenshot, that's strong evidence of a genuine hypervisor-level freeze rather than a host-side mouse-capture/focus issue (which injected scancodes bypass entirely, since they go straight to the virtual keyboard controller).
  • VBox.log timestamps as a liveness signal — if the guest's own internal clock (the timestamps prefixing each log line) stops advancing across multiple real-time-spaced checks, the guest is truly stalled, not just quietly working. A guest doing real background work (e.g. slow disk I/O) keeps producing new timestamped entries even if nothing user-visible changes.