containerd/containerd · error

failed to create base vhd: %w

Error message

failed to create base vhd: %w

What it means

The base scratch VHD could not be created by createScratchVHD (with NTFS formatting) when it did not already exist. createDifferencingScratchVHDs wraps the underlying failure — which itself may be an option-application error, stat failure, or a vhd.CreateVirtualDisk/format failure — and cleanup removes partial files afterward.

Source

Thrown at plugins/snapshots/windows/cimfs.go:424

	if err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("failed to stat diff VHD: %w", err)
	} else if baseVHDExists && err == nil {
		diffVHDExists = true
	} else {
		// remove this diff VHD, it must be recreated with the new base VHD.
		os.RemoveAll(diffVHDPath)
	}

	defer func() {
		if err != nil {
			os.RemoveAll(baseVHDPath)
			os.RemoveAll(diffVHDPath)
		}
	}()

	if !baseVHDExists {
		if err = createScratchVHD(ctx, baseVHDPath, WithNTFSFormat()); err != nil {
			return fmt.Errorf("failed to create base vhd: %w", err)
		}
	}

	if !diffVHDExists {
		// Create the differencing disk that will be what's copied for the final rw layer
		// for a container.
		if err = vhd.CreateDiffVhd(diffVHDPath, baseVHDPath, vhdBlockSizeInBytes); err != nil {
			return fmt.Errorf("failed to create differencing disk: %w", err)
		}
	}

	// Grant VM group access to the differencing VHD (base VHD access is already granted by createSingleVHD)
	if err = security.GrantVmGroupAccess(diffVHDPath); err != nil {
		return fmt.Errorf("failed to grant vm group access to %s: %w", diffVHDPath, err)
	}
	return nil
}

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Unwrap to the root cause from createScratchVHD and fix it (space, permissions, VDS availability).
  2. Free disk space on the volume hosting the snapshotter root.
  3. Ensure containerd runs elevated enough to create virtual disks (Virtual Disk APIs).
  4. Check that security software isn't blocking vhd image creation; delete any corrupt leftover base VHD and restart containerd.

Example fix

// before: full disk
// after: free space then re-init
// Get-Volume C  # verify free space
// Restart-Service containerd
Defensive patterns

Strategy: validation

Validate before calling

func precheckBaseVHDCreation(baseVHDPath string, needBytes uint64) error {
    if fi, err := os.Stat(filepath.Dir(baseVHDPath)); err != nil || !fi.IsDir() {
        return fmt.Errorf("scratch dir missing or invalid")
    }
    if free, err := freeDiskSpace(filepath.VolumeName(baseVHDPath)); err != nil || free < needBytes {
        return fmt.Errorf("insufficient space for base VHD")
    }
    return nil
}

Try / catch

if err := createScratchVHD(ctx, baseVHDPath, WithNTFSFormat()); err != nil {
    if errors.Is(err, os.ErrExist) { os.Remove(baseVHDPath); retry() }
    else if isDiskFull(err) { freeSpace(); retry() }
    else { return fmt.Errorf("cannot create base vhd, check VDS/privileges: %w", err) }
}

Prevention

When it happens

Trigger: First snapshotter init (baseVHDExists==false) calls createScratchVHD(ctx, baseVHDPath, WithNTFSFormat()); the underlying vhd.CreateVirtualDisk, VHD mount/format step, or an option callback fails (no disk space, Virtual Disk Service unavailable, insufficient privileges).

Common situations: Disk full on the containerd volume; Windows Virtual Disk Service (vds) or vhdx APIs blocked by policy/security software; running containerd without required privileges; file already exists as a corrupt leftover handled by the wrong branch.

Related errors


AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02). Data as JSON: /api/errors/cbbb1d75ced16ee5. Report an issue: GitHub.