# Upstream issue draft — file at microsoft/hcsshim (cross-reference moby/buildkit)

Status: READY TO FILE (2026-08-04). Not yet submitted.
Where: https://github.com/microsoft/hcsshim/issues/new (primary),
cross-ref in https://github.com/moby/buildkit/issues (secondary ask below).

---

## Title

Process-isolated WCOW: HCS shutdown notification never delivered after
heavy-IO builds; scratch never released; snapshot commit permanently fails
with `hcsshim::ExportLayer 0x3`

## Environment

- Host: Windows 11 Pro, build 10.0.26200
- Guest image: `mcr.microsoft.com/windows/servercore:ltsc2025`
  (`sha256:d5bbb83057f6bc2b6aeba5d01ec80a53003aba9bc84a6b1ebe780570cd52558a`)
- containerd (Stevedore distribution) + BuildKit v0.32.0 (`buildctl`),
  windows snapshotter, **process isolation**
- Repro rate: 100 % for specific build workloads (11+ occurrences), 0 % for
  others — fully deterministic per workload, survives a host reboot with a
  fresh container

## Symptom

`buildctl` solves fail at layer finalize:

```
failed to commit <active> to <name> during finalize: failed to reimport
snapshot: hcsshim::ExportLayer failed in Win32: Das System kann den
angegebenen Pfad nicht finden. (0x3)
```

## Debug-log timeline (containerd --log-level debug) — two independent runs

```
07:58:52.681 level=error msg="timed out while waiting for container shutdown"  error="hcsshim: timeout waiting for notification" timeout=30s
07:59:22.681 level=error msg="timed out while waiting for container terminate" error="hcsshim: timeout waiting for notification" timeout=30s
07:59:23.15x shim cleanup: HcsWaitForOperationResult fails with
             "Der angeforderte virtuelle Computer- oder Containervorgang ist
             im aktuellen Zustand ungültig." (HCS_E_INVALID_STATE,
             resultDocument Error -1070137083)
07:59:23.178 level=debug msg="commit snapshot" key=n4yps6... name=svgf6...
07:59:36.235 level=debug msg="snapshotter error" error="failed to reimport
             snapshot: hcsshim::ExportLayer ... (0x3)"
```

Second run, identical shape: shutdown timeout 08:26:52 → terminate timeout
08:27:22 → commit 08:27:22.826 → ExportLayer 0x3 at 08:27:35.631.

**Host process inspection immediately after the timeouts shows NO surviving
container processes** — every process in the silo exited; only the HCS
completion notification never reached hcsshim. The scratch layer is then
never cleanly deactivated/released, and every subsequent ExportLayer of that
snapshot fails 0x3, indefinitely (retries minutes or hours later, and even
after buildkitd/containerd restarts, still fail on that snapshot).

## Trigger matrix (~20 controlled probes)

Fails 100 % (fresh snapshot each time): cmake/MSBuild ONNXRuntime-GenAI
(~7 min, ~4 GB diff), cmake+ninja OpenCV (~21 min), cmake+ninja TVM+IREE
(~15 min), meson/ninja GStreamer (~30 min).

Succeeds 100 %: 100-minute ninja ONNXRuntime build (12 GB diff!), MSBuild
cpython build, bazel LiteRT build (24 min), pip-heavy torch app assemble,
`MSBuild.exe -version`, 14 stacked trivial layers.

Ruled out by probes: layer content (a failing build whose ENTIRE file diff
was deleted before step end still fails), lingering compiler daemons (killed
before exit — still fails), msdtc/WMI services (stopped — still fails), 30 s
quiesce sleep + volume flush, host reboot + fresh container, cache
poisoning, layer depth, parent-layer integrity, .NET Framework CLR startup
alone.

## Two distinct problems

1. **hcsshim/HCS**: the shutdown/terminate notification is lost although all
   silo processes exited (both 30 s waits time out back-to-back). Ask:
   what makes HCS drop the notification for these containers (host 26200 vs
   ltsc2025 guest skew? wcifs churn volume?), and could hcsshim fall back to
   polling system state instead of relying solely on the callback?
2. **containerd windows snapshotter / BuildKit** (secondary, cross-ref):
   the snapshot commit proceeds ~70 ms into a teardown that demonstrably
   failed; the resulting 0x3 surfaces far from the root cause, and the cache
   record becomes permanently unreclaimable ("shared", pinned by an orphaned
   lease that only a buildkitd restart frees). Ask: fail fast or
   deactivate/retry the scratch when teardown reported failure.

## Workaround in production (for other affected users)

Exploit BuildKit's lazy finalization: run the heavy build in a solve with NO
exporter (its snapshot is never finalized), move the artifacts out through a
side channel (we use one tar over a LAN WebDAV server), and materialize them
in a calm, short-lived container whose snapshot finalizes normally. Details:
`docs/windows-builds.md` § BuildKit/containerd lane in
https://github.com/Kataglyphis/Kataglyphis-ContainerHub.

Full containerd debug logs and per-probe build logs available on request.
