{"record":{"id":"03b57629a0addacc","repo":"docker/cli","slug":"volume-prune-has-been-cancelled","errorCode":null,"errorMessage":"volume prune has been cancelled","messagePattern":"volume prune has been cancelled","errorType":"exception","errorClass":"cancelledErr","httpStatus":null,"severity":"warning","filePath":"cli/command/volume/prune.go","lineNumber":89,"sourceCode":"\nfunc runPrune(ctx context.Context, dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint64, output string, _ error) {\n\tpruneFilters := command.PruneFilters(dockerCli, options.filter.Value())\n\n\twarning := unusedVolumesWarning\n\tif options.all {\n\t\tif _, ok := pruneFilters[\"all\"]; ok {\n\t\t\treturn 0, \"\", invalidParamErr{errors.New(\"conflicting options: cannot specify both --all and --filter all=1\")}\n\t\t}\n\t\tpruneFilters.Add(\"all\", \"true\")\n\t\twarning = allVolumesWarning\n\t}\n\tif !options.force {\n\t\tr, err := prompt.Confirm(ctx, dockerCli.In(), dockerCli.Out(), warning)\n\t\tif err != nil {\n\t\t\treturn 0, \"\", err\n\t\t}\n\t\tif !r {\n\t\t\treturn 0, \"\", cancelledErr{errors.New(\"volume prune has been cancelled\")}\n\t\t}\n\t}\n\n\tres, err := dockerCli.Client().VolumePrune(ctx, client.VolumePruneOptions{\n\t\tFilters: pruneFilters,\n\t})\n\tif err != nil {\n\t\treturn 0, \"\", err\n\t}\n\n\tvar out strings.Builder\n\tif len(res.Report.VolumesDeleted) > 0 {\n\t\tout.WriteString(\"Deleted Volumes:\\n\")\n\t\tfor _, id := range res.Report.VolumesDeleted {\n\t\t\tout.WriteString(id + \"\\n\")\n\t\t}\n\t\tspaceReclaimed = res.Report.SpaceReclaimed\n\t}","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/volume/prune.go#L71-L107","documentation":"Returned by runPrune (volume/prune.go:88-90) when the user is shown the prune warning prompt and answers 'no' (or anything not interpreted as confirmation) and --force was not given. The error is wrapped in cancelledErr (which satisfies Cancelled()), signalling an intentional cancellation rather than a failure.","triggerScenarios":"Running 'docker volume prune' (without -f/--force) and typing 'n' or an empty/invalid answer at the 'Are you sure you want to continue?' prompt (prune.go:84 uses prompt.Confirm).","commonSituations":"Interactive session where the user hesitates. Non-interactive piping of 'n' into stdin. A CI/automation step that forgot --force and gets a non-yes answer.","solutions":["If you intended to prune, re-run and answer 'y' at the prompt, or pass --force/-f to skip it.","In automation, always pass '-f' so no prompt is issued.","Treat a cancelledErr as expected (not a hard failure) in scripts - check the Cancelled() marker rather than treating exit code as fatal."],"exampleFix":"# before\ndocker volume prune          # then type n\n\n# after (automation)\ndocker volume prune --force","handlingStrategy":"validation","validationCode":"// For non-interactive runs, pass --force to avoid the prompt entirely.\nfunc volumePruneCmd(force bool) []string {\n    if force {\n        return []string{\"volume\", \"prune\", \"--force\"}\n    }\n    return []string{\"volume\", \"prune\"}\n}","typeGuard":"// isCancelled reports whether an error from prune is a user cancellation (not a failure).\n// Mirror the CLI's cancelledErr.Cancelled() marker.\ntype cancelled interface{ Cancelled() bool }\nfunc isCancelled(err error) bool {\n    var c cancelled\n    return errors.As(err, &c) // adapt to your error-wrapping library\n}","tryCatchPattern":"// Treat cancellation as an expected, non-fatal outcome.\nif _, err := runPrune(ctx, cli, opts); err != nil {\n    if isCancelled(err) {\n        // user declined; proceed without pruning\n        return nil\n    }\n    return err\n}","preventionTips":["In automation always pass --force/-f to skip the prompt.","Detect the Cancelled() error marker and treat it as expected, not fatal.","Provide explicit 'y'/'n' on stdin only in interactive contexts."],"tags":["docker-volume","prune","cancellation","interactive-prompt"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}