{"record":{"id":"ddcdaf8cca013371","repo":"docker/compose","slug":"unsupported-image-prune-mode-s","errorCode":null,"errorMessage":"unsupported image prune mode: %s","messagePattern":"unsupported image prune mode: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compose/image_pruner.go","lineNumber":78,"sourceCode":"type ImagePruner struct {\n\tclient  client.ImageAPIClient\n\tproject *types.Project\n}\n\n// NewImagePruner creates an ImagePruner object for a project.\nfunc NewImagePruner(imageClient client.ImageAPIClient, project *types.Project) *ImagePruner {\n\treturn &ImagePruner{\n\t\tclient:  imageClient,\n\t\tproject: project,\n\t}\n}\n\n// ImagesToPrune returns the set of images that should be removed.\nfunc (p *ImagePruner) ImagesToPrune(ctx context.Context, opts ImagePruneOptions) ([]string, error) {\n\tif opts.Mode == ImagePruneNone {\n\t\treturn nil, nil\n\t} else if opts.Mode != ImagePruneLocal && opts.Mode != ImagePruneAll {\n\t\treturn nil, fmt.Errorf(\"unsupported image prune mode: %s\", opts.Mode)\n\t}\n\tvar images []string\n\n\tif opts.Mode == ImagePruneAll {\n\t\tnamedImages, err := p.namedImages(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\timages = append(images, namedImages...)\n\t}\n\n\tprojectImages, err := p.labeledLocalImages(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, img := range projectImages {\n\t\tif len(img.RepoTags) == 0 {\n\t\t\t// currently, we're only pruning the tagged references, but","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/compose/image_pruner.go#L60-L96","documentation":"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`.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass one of the typed constants: compose.ImagePruneNone, compose.ImagePruneLocal, or compose.ImagePruneAll","If mapping from a CLI flag, validate/normalize the string (empty means none) before assigning Mode","Upgrade the compose module if you expect a mode the current version does not know"],"exampleFix":"// before\nopts := compose.ImagePruneOptions{Mode: compose.ImagePruneMode(\"locall\")}\n_, err := pruner.ImagesToPrune(ctx, opts)\n\n// after\nopts := compose.ImagePruneOptions{Mode: compose.ImagePruneLocal}\n_, err := pruner.ImagesToPrune(ctx, opts)","handlingStrategy":"validation","validationCode":"func validPruneMode(m compose.ImagePruneMode) bool {\n    switch m {\n    case compose.ImagePruneNone, compose.ImagePruneLocal, compose.ImagePruneAll:\n        return true\n    }\n    return false\n}\n// call before ImagesToPrune\nif !validPruneMode(opts.Mode) { return fmt.Errorf(\"bad prune mode %q\", opts.Mode) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only assign Mode from the package constants, never from raw strings","Map CLI flags to constants through a single switch so unknown values fail at the edge"],"tags":["images","prune","validation","api-misuse"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}