containerd/containerd · error

failed to set volume mount path for layer %s: %w

Error message

failed to set volume mount path for layer %s: %w

What it means

Returned by Mount.mount on Windows when bindfilter.ApplyFileBinding fails to bind the layer volume path to the requested target. This is the final filesystem-binding step after activation, preparation, and mount-path resolution; the wrapped error comes from the bind-filter driver. On failure the deferred cleanup removes any partial binding at the target.

Source

Thrown at core/mount/mount_windows.go:91

			}
		}
	}()

	volume, err := hcsshim.GetLayerMountPath(di, layerID)
	if err != nil {
		return fmt.Errorf("failed to get volume path for layer %s: %w", m.Source, err)
	}

	if len(parentLayerPaths) == 0 {
		// this is a base layer. It gets mounted without going through WCIFS. We need to mount the Files
		// folder, not the actual source, or the client may inadvertently remove metadata files.
		volume = filepath.Join(volume, "Files")
		if _, err := os.Stat(volume); err != nil {
			return fmt.Errorf("no Files folder in layer %s", layerID)
		}
	}
	if err := bindfilter.ApplyFileBinding(target, volume, m.ReadOnly()); err != nil {
		return fmt.Errorf("failed to set volume mount path for layer %s: %w", m.Source, err)
	}
	defer func() {
		if retErr != nil {
			if bindErr := bindfilter.RemoveFileBinding(target); bindErr != nil {
				log.G(context.TODO()).WithError(bindErr).Error("failed to remove binding during mount failure cleanup")
			}
		}
	}()

	// Add an Alternate Data Stream to record the layer source.
	// See https://docs.microsoft.com/en-au/archive/blogs/askcore/alternate-data-streams-in-ntfs
	// for details on Alternate Data Streams.
	if err := os.WriteFile(filepath.Clean(target)+":"+sourceStreamName, []byte(m.Source), 0666); err != nil {
		return fmt.Errorf("failed to record source for layer %s: %w", m.Source, err)
	}

	return nil
}

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Ensure the target path is free of stale bindings; call the unmount path (which invokes bindfilter.RemoveFileBinding) or remove leftover junctions, then retry
  2. Check the Windows host has the bind filter driver available and updated (upgrade Windows/containerd if unsupported)
  3. Avoid concurrent mounts to the same target; serialize mount operations per target path
  4. Check permissions on target and volume paths, and Windows event logs for bindfilter errors
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure target has no stale binding before mounting
if _, err := os.Stat(filepath.Join(target, "Files")); err == nil {
    // path already populated: a previous binding may be present
    _ = mount.UnmountAll(target, 0)
}

Type guard

func isBindFilterError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "failed to set volume mount path for layer ")
}

Try / catch

err := mount.All(mounts, target)
if isBindFilterError(err) {
    // clear stale binding, then retry once
    _ = mount.UnmountAll(target, 0)
    return mount.All(mounts, target)
}

Prevention

When it happens

Trigger: Calling Mount with Type 'windows-layer' when the bind filter cannot create the binding: target path already bound/in use, target invalid or locked, read-only flag unsupported in current state, or the bindfilter driver (Windows feature) is unavailable or failing.

Common situations: Target directory already used by another mount (stale binding from a previous failed mount); missing/failed Windows bind filter driver on the host; path conflicts with existing directories or junctions; concurrent mounts racing on the same target path; host with outdated/unsupported Windows build.

Related errors


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