docker/compose · error

unsupported image prune mode: %s

Error message

unsupported image prune mode: %s

What it means

ImagePruner.ImagesToPrune validates opts.Mode before doing any work: only ImagePruneNone (no-op), ImagePruneLocal and ImagePruneAll are accepted. Any other value is a programming error and rejected immediately. This backs `docker compose down --rmi`.

Source

Thrown at pkg/compose/image_pruner.go:78

type ImagePruner struct {
	client  client.ImageAPIClient
	project *types.Project
}

// NewImagePruner creates an ImagePruner object for a project.
func NewImagePruner(imageClient client.ImageAPIClient, project *types.Project) *ImagePruner {
	return &ImagePruner{
		client:  imageClient,
		project: project,
	}
}

// ImagesToPrune returns the set of images that should be removed.
func (p *ImagePruner) ImagesToPrune(ctx context.Context, opts ImagePruneOptions) ([]string, error) {
	if opts.Mode == ImagePruneNone {
		return nil, nil
	} else if opts.Mode != ImagePruneLocal && opts.Mode != ImagePruneAll {
		return nil, fmt.Errorf("unsupported image prune mode: %s", opts.Mode)
	}
	var images []string

	if opts.Mode == ImagePruneAll {
		namedImages, err := p.namedImages(ctx)
		if err != nil {
			return nil, err
		}
		images = append(images, namedImages...)
	}

	projectImages, err := p.labeledLocalImages(ctx)
	if err != nil {
		return nil, err
	}
	for _, img := range projectImages {
		if len(img.RepoTags) == 0 {
			// currently, we're only pruning the tagged references, but

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Pass one of the typed constants: compose.ImagePruneNone, compose.ImagePruneLocal, or compose.ImagePruneAll
  2. If mapping from a CLI flag, validate/normalize the string (empty means none) before assigning Mode
  3. Upgrade the compose module if you expect a mode the current version does not know

Example fix

// before
opts := compose.ImagePruneOptions{Mode: compose.ImagePruneMode("locall")}
_, err := pruner.ImagesToPrune(ctx, opts)

// after
opts := compose.ImagePruneOptions{Mode: compose.ImagePruneLocal}
_, err := pruner.ImagesToPrune(ctx, opts)
Defensive patterns

Strategy: validation

Validate before calling

func validPruneMode(m compose.ImagePruneMode) bool {
    switch m {
    case compose.ImagePruneNone, compose.ImagePruneLocal, compose.ImagePruneAll:
        return true
    }
    return false
}
// call before ImagesToPrune
if !validPruneMode(opts.Mode) { return fmt.Errorf("bad prune mode %q", opts.Mode) }

Prevention

When it happens

Trigger: Calling ImagesToPrune with opts.Mode set to an empty string or a value other than the local/all/none constants, e.g. a typo like "locall" or a newly invented mode on an older compose version.

Common situations: Go code embedding pkg/compose passing a raw string mode instead of the typed constants; version skew where a caller uses a mode constant added in a newer compose than the linked library.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/ddcdaf8cca013371. Report an issue: GitHub.