containerd/containerd · error
failed to find UtilityVM directory in base layer %q: %w
Error message
failed to find UtilityVM directory in base layer %q: %w
What it means
createUVMScratchLayer builds a scratch layer for a Utility VM from a base Windows layer. It requires the base (last parent) layer to contain a UtilityVM directory; if os.Stat finds it missing, this error reports which base layer path lacks it. Utility VM images are only produced for Windows process/hypervisor-isolated base images that include the UVM components.
Source
Thrown at plugins/snapshots/windows/common.go:212
}
// Close closes the snapshotter
func (w *windowsBaseSnapshotter) Close() error {
return w.ms.Close()
}
// This handles creating the UVMs scratch layer.
func (w *windowsBaseSnapshotter) createUVMScratchLayer(ctx context.Context, snDir string, parentLayers []string) error {
parentLen := len(parentLayers)
if parentLen == 0 {
return errors.New("no parent layers present")
}
baseLayer := parentLayers[parentLen-1]
// Make sure base layer has a UtilityVM folder.
uvmPath := filepath.Join(baseLayer, "UtilityVM")
if _, err := os.Stat(uvmPath); os.IsNotExist(err) {
return fmt.Errorf("failed to find UtilityVM directory in base layer %q: %w", baseLayer, err)
}
templateDiffDisk := filepath.Join(uvmPath, "SystemTemplate.vhdx")
// Check if SystemTemplate disk doesn't exist for some reason (this should be made during the unpacking
// of the base layer).
if _, err := os.Stat(templateDiffDisk); os.IsNotExist(err) {
return fmt.Errorf("%q does not exist in Utility VM image", templateDiffDisk)
}
// Move the sandbox.vhdx into a nested vm folder to avoid clashing with a containers sandbox.vhdx.
vmScratchDir := filepath.Join(snDir, "vm")
if err := os.MkdirAll(vmScratchDir, 0777); err != nil {
return fmt.Errorf("failed to make `vm` directory for vm's scratch space: %w", err)
}
return copyScratchDisk(templateDiffDisk, filepath.Join(vmScratchDir, "sandbox.vhdx"))
}View on GitHub (pinned to 4246446a2b)
Solutions
- Verify the base image is a Windows base layer that ships a UtilityVM directory (check the layer on disk)
- Re-pull/re-extract the base image — a corrupted or partial unpack may have dropped UtilityVM
- Ensure you are not mistakenly passing a non-base (child) layer as the last parent
- Use an image built for the matching Windows build/hypervisor isolation scenario
Defensive patterns
Strategy: validation
Validate before calling
// Before invoking the UVM scratch path, verify the base layer
uvmDir := filepath.Join(baseLayerPath, "UtilityVM")
if fi, err := os.Stat(uvmDir); err != nil || !fi.IsDir() {
return fmt.Errorf("base layer %s lacks UtilityVM dir", baseLayerPath)
} Try / catch
if err != nil && strings.Contains(err.Error(), "failed to find UtilityVM directory") {
return fmt.Errorf("image is not a Windows UVM-capable base layer: %w", err)
} Prevention
- Only use official Windows base images that include UtilityVM for hyper-v isolation
- Verify image unpack completed successfully before creating UVM scratch layers
- Pin image digests to known-good Windows base images
- Match base image version to the host Windows build
When it happens
Trigger: Calling createUVMScratchLayer (via the anonymous snapshotter path) with parentLayers whose final entry has no UtilityVM subdirectory — i.e. the base image was not a proper Windows base layer with UVM support.
Common situations: Using a nanoserver/servercore variant or custom image without UtilityVM contents as the base for a hyper-v snapshotter; layer unpacking partially failed so UtilityVM was never written; pointing the snapshotter at the wrong parent layer list.
Related errors
- %q does not exist in Utility VM image
- failed to make `vm` directory for vm's scratch space: %w
- media type not found
- windows stats is empty
- xattrs not supported on Windows
AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02).
Data as JSON: /api/errors/9f27e189d94a08f6.
Report an issue: GitHub.