containerd/containerd · error

failed to create '%s' temp file: %w

Error message

failed to create '%s' temp file: %w

What it means

Thrown by openOrCreateScratch when runhcs.CreateScratchWithOpts fails to create the temporary scratch VHD file. The temp file is removed and the underlying runhcs error (typically a runhcs invocation failure) is wrapped. This means the Hyper-V/container host tooling could not produce a blank scratch.vhdx of the requested size.

Source

Thrown at plugins/snapshots/lcow/lcow.go:470

		scratchTempName := fmt.Sprintf("scratch-%s-tmp.vhdx", strconv.Itoa(int(1e9 + r%1e9))[1:])
		scratchTempPath := filepath.Join(s.root, scratchTempName)

		// Create the scratch
		rhcs := runhcs.Runhcs{
			Debug:     true,
			Log:       filepath.Join(s.root, "runhcs-scratch.log"),
			LogFormat: runhcs.JSON,
			Owner:     "containerd",
		}

		opt := runhcs.CreateScratchOpts{
			SizeGB: sizeGB,
		}

		if err := rhcs.CreateScratchWithOpts(ctx, scratchTempPath, &opt); err != nil {
			os.Remove(scratchTempPath)
			return nil, fmt.Errorf("failed to create '%s' temp file: %w", scratchTempName, err)
		}
		if err := os.Rename(scratchTempPath, scratchFinalPath); err != nil {
			os.Remove(scratchTempPath)
			return nil, fmt.Errorf("failed to rename '%s' temp file to 'scratch.vhdx': %w", scratchTempName, err)
		}
		scratchSource, err = os.OpenFile(scratchFinalPath, os.O_RDONLY, 0700)
		if err != nil {
			os.Remove(scratchFinalPath)
			return nil, fmt.Errorf("failed to open scratch.vhdx for read after creation: %w", err)
		}
	} else {
		log.G(ctx).Debugf("scratch vhd %s was already present. Retrieved from cache", vhdFileName)
	}
	return scratchSource, nil
}

func (s *snapshotter) parentIDsToParentPaths(parentIDs []string) []string {
	var parentLayerPaths []string

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Verify runhcs.exe is present and functional on PATH (run `runhcs --version`) and matches your containerd version
  2. Enable required Windows features: Hyper-V and Containers (Install-WindowsFeature Hyper-V, Containers)
  3. Free disk space on the volume hosting the snapshot root or reduce the requested sizeGB
  4. Check the wrapped runhcs error output in logs for the concrete Win32/HCS failure code

Example fix

// before: LCOW snapshotter on host without Hyper-V
Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart
// after: scratch creation succeeds via runhcs
Defensive patterns

Strategy: retry

Validate before calling

const hyperVReady = await run('powershell -c "(Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V).State"')
if (!hyperVReady.includes('Enabled')) throw new Error('Enable Hyper-V before LCOW snapshots')
const freeGB = await getFreeDiskGB(snapshotRoot)
if (freeGB < requestedSizeGB * 1.1) throw new Error('insufficient disk space for scratch creation')

Type guard

function isRunhcsError(e: unknown): e is Error & { stderr?: string } {
  return e instanceof Error && 'stderr' in e
}

Try / catch

try {
  await createSnapshotWithScratch(sizeGB)
} catch (err) {
  if (isTransient(err)) return retryWithBackoff(err)
  log.error('scratch creation failed; verify runhcs and Hyper-V', err)
  throw err
}

Prevention

When it happens

Trigger: rhcs.CreateScratchWithOpts(ctx, scratchTempPath, &opt) returns an error while creating a new scratch VHD (missing or broken runhcs.exe, Hyper-V not enabled, invalid sizeGB, insufficient disk space).

Common situations: Running LCOW containers on a Windows host without the Hyper-V feature/Host Compute Service installed; runhcs version mismatch with containerd; disk-full on the snapshot volume; requesting a scratch size larger than the available disk.

Related errors


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