{"record":{"id":"b095329fb0aa9355","repo":"docker/cli","slug":"system-prune-has-been-cancelled","errorCode":null,"errorMessage":"system prune has been cancelled","messagePattern":"system prune has been cancelled","errorType":"exception","errorClass":"cancelledErr","httpStatus":null,"severity":"warning","filePath":"cli/command/system/prune.go","lineNumber":87,"sourceCode":"Are you sure you want to continue?`\n\nfunc runPrune(ctx context.Context, dockerCli command.Cli, options pruneOptions) error {\n\t// prune requires either force, or a user to confirm after prompting.\n\tconfirmed := options.force\n\n\t// Validate the given options for each pruner and construct a confirmation-message.\n\tconfirmationMessage, err := dryRun(ctx, dockerCli, options)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !confirmed {\n\t\tvar err error\n\t\tconfirmed, err = prompt.Confirm(ctx, dockerCli.In(), dockerCli.Out(), confirmationMessage)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !confirmed {\n\t\t\treturn cancelledErr{errors.New(\"system prune has been cancelled\")}\n\t\t}\n\t}\n\n\tvar spaceReclaimed uint64\n\tfor contentType, pruneFn := range pruner.List() {\n\t\tswitch contentType {\n\t\tcase pruner.TypeVolume:\n\t\t\tif !options.pruneVolumes {\n\t\t\t\tcontinue\n\t\t\t}\n\t\tcase pruner.TypeContainer, pruner.TypeNetwork, pruner.TypeImage, pruner.TypeBuildCache:\n\t\t\t// no special handling; keeping the \"exhaustive\" linter happy.\n\t\tdefault:\n\t\t\t// other pruners; no special handling; keeping the \"exhaustive\" linter happy.\n\t\t}\n\n\t\tspc, output, err := pruneFn(ctx, dockerCli, pruner.PruneOptions{\n\t\t\tConfirmed: confirmed,","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/system/prune.go#L69-L105","documentation":"Returned by runPrune (cli/command/system/prune.go:87) wrapped in a cancelledErr when the user declines the confirmation prompt (and --force was not set). It is a controlled cancellation — cancelledErr implements the Cancelled() marker method — not a system failure; distinguish it from real prune errors.","triggerScenarios":"Running `docker system prune` interactively and answering 'n' (or anything non-affirmative) at the 'Are you sure you want to continue?' prompt; a non-interactive invocation where the input stream yields no confirmation.","commonSituations":"Cautious operator declines; a script forgot `--force` and the TTY/piped input doesn't confirm; CI harness that expects pruning but didn't pass -f.","solutions":["Answer 'y' to confirm at the prompt.","Use `--force`/`-f` to skip the prompt in scripts: `docker system prune -f`.","Detect cancellation programmatically by checking for the `Cancelled()` method on the returned error."],"exampleFix":"// before\ndocker system prune   # -> types 'n' -> system prune has been cancelled\n\n// after (scripts)\ndocker system prune --force\n# or programmatically detect cancellation:\n// var c interface{ Cancelled() }\n// if errors.As(err, &c) { /* user cancelled, not a failure */ }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// Detect a user-initiated cancellation vs a real prune failure.\nfunc isCancelled(err error) bool {\n\tvar c interface{ Cancelled() }\n\treturn errors.As(err, &c)\n}","tryCatchPattern":"err := runPrune(ctx, dockerCli, options)\nif err != nil {\n\tvar c interface{ Cancelled() }\n\tif errors.As(err, &c) {\n\t\t// user declined the prompt — not a failure; exit 0 or log and continue\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Pass --force in non-interactive/CI contexts to avoid the prompt.","Treat cancelledErr (Cancelled()) as a soft cancel, not a hard failure.","Confirm TTY availability before relying on interactive prompts in automation."],"tags":["docker","system","prune","confirmation","cancelled"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}