{"record":{"id":"ff4968474657e937","repo":"docker/cli","slug":"container-prune-has-been-cancelled","errorCode":null,"errorMessage":"container prune has been cancelled","messagePattern":"container prune has been cancelled","errorType":"console","errorClass":"cancelledErr","httpStatus":null,"severity":"info","filePath":"cli/command/container/prune.go","lineNumber":74,"sourceCode":"\tflags.BoolVarP(&options.force, \"force\", \"f\", false, \"Do not prompt for confirmation\")\n\tflags.Var(&options.filter, \"filter\", `Provide filter values (e.g. \"until=<timestamp>\")`)\n\n\treturn cmd\n}\n\nconst warning = `WARNING! This will remove all stopped containers.\nAre you sure you want to continue?`\n\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\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(\"container prune has been cancelled\")}\n\t\t}\n\t}\n\n\tres, err := dockerCli.Client().ContainerPrune(ctx, client.ContainerPruneOptions{\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.ContainersDeleted) > 0 {\n\t\tout.WriteString(\"Deleted Containers:\\n\")\n\t\tfor _, id := range res.Report.ContainersDeleted {\n\t\t\tout.WriteString(id + \"\\n\")\n\t\t}\n\t\tspaceReclaimed = res.Report.SpaceReclaimed\n\t}","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/container/prune.go#L56-L92","documentation":"Returned by runPrune wrapped in a cancelledErr (which implements Cancelled()) when the user answers 'no' to the interactive prune confirmation prompt. It is not a daemon failure; it signals the operation was intentionally aborted by the user. The prompt only appears when --force is not set.","triggerScenarios":"Running `docker container prune` (without -f) and typing 'n' at the 'Are you sure you want to continue?' prompt, or piping 'n'/'no' into stdin. prompt.Confirm returns false and the function returns the cancelled error.","commonSituations":"Interactive scripts that auto-answer 'n'. CI wrappers echoing 'n' to avoid accidental deletion. Aborted cleanup during manual exploration.","solutions":["Re-run and confirm with 'y', or use `docker container prune -f` to skip the prompt.","In scripts, detect the Cancelled() error type and treat it as a no-op rather than a failure.","Ensure stdin is a TTY if you want the prompt to appear interactively."],"exampleFix":"// before\ndocker container prune   # user typed 'n'\n\n// after\ndocker container prune -f","handlingStrategy":"try-catch","validationCode":"// If non-interactive, default force=true to skip the prompt entirely.\nif !interactive {\n    options.force = true\n}","typeGuard":"// Detect a user cancellation by the Cancelled() marker interface.\nfunc isCancelled(err error) bool {\n    var c interface{ Cancelled() }\n    return errors.As(err, &c)\n}","tryCatchPattern":"_, _, err := runPrune(ctx, cli, options)\nif err != nil {\n    var c interface{ Cancelled() }\n    if errors.As(err, &c) {\n        // user declined — not a failure\n        return nil\n    }\n    return err\n}","preventionTips":["Pass --force in non-interactive scripts to avoid the prompt entirely.","Always check for the Cancelled() interface to distinguish aborts from real errors.","Ensure stdin is a TTY for interactive confirmation, or pre-pipe 'y'/'n' deliberately."],"tags":["prune","user-cancellation","container","interactive"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}