containerd/containerd · error · errdefs.ErrInvalidArgument

number of mounts should always be 1 for Windows lcow-layers:

Error message

number of mounts should always be 1 for Windows lcow-layers: %w

What it means

mountsToLayerAndParents requires exactly one mount entry, because an LCOW layer application maps to a single lcow-layer mount whose VHD is copied out. If Apply receives a mount slice whose length is not 1, it returns this error wrapping errdefs.ErrInvalidArgument.

Source

Thrown at plugins/diff/lcow/lcow.go:204

// to the content store.
func (s windowsLcowDiff) Compare(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt) (d ocispec.Descriptor, err error) {
	return emptyDesc, fmt.Errorf("windowsLcowDiff does not implement Compare method: %w", errdefs.ErrNotImplemented)
}

type readCounter struct {
	r io.Reader
	c int64
}

func (rc *readCounter) Read(p []byte) (n int, err error) {
	n, err = rc.r.Read(p)
	rc.c += int64(n)
	return
}

func mountsToLayerAndParents(mounts []mount.Mount) (string, []string, error) {
	if len(mounts) != 1 {
		return "", nil, fmt.Errorf("number of mounts should always be 1 for Windows lcow-layers: %w", errdefs.ErrInvalidArgument)
	}
	mnt := mounts[0]
	if mnt.Type != "lcow-layer" {
		return "", nil, fmt.Errorf("mount layer type must be lcow-layer: %w", errdefs.ErrNotImplemented)
	}

	parentLayerPaths, err := mnt.GetParentPaths()
	if err != nil {
		return "", nil, err
	}

	return mnt.Source, parentLayerPaths, nil
}

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Ensure the mount list passed to Apply comes from an LCOW snapshotter (exactly one lcow-layer mount).
  2. Inspect the mounts slice before calling Apply; log len(mounts) and reject non-single-mount inputs in the caller.
  3. If multiple parent layers are involved, verify parents are represented via the mount's ParentPaths, not as extra mount entries.

Example fix

// before
desc, err := differ.Apply(ctx, mounts)
// after
if len(mounts) != 1 {
    return fmt.Errorf("lcow differ requires exactly 1 mount, got %d", len(mounts))
}
desc, err := differ.Apply(ctx, mounts)
Defensive patterns

Strategy: validation

Validate before calling

if len(mounts) != 1 {
    return fmt.Errorf("lcow Apply needs exactly 1 mount, got %d", len(mounts))
}

Try / catch

if err := differ.Apply(ctx, mounts); err != nil && strings.Contains(err.Error(), "number of mounts should always be 1") {
    // fix mount sourcing; do not retry unchanged input
}

Prevention

When it happens

Trigger: Calling windowsLcowDiff.Apply with mounts containing 0 or 2+ entries - e.g. passing multiple layered mounts, an empty mounts slice, or a mounts list intended for a Linux-style overlay snapshotter.

Common situations: Misconfigured snapshotter output, code written for Linux overlay diffs (which pass multiple mounts) being run against the Windows LCOW differ, or snapshot metadata corruption.

Related errors


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