{"id":"7957d6ffb23d498d","repo":"docker/cli","slug":"error-registering-pruner-invalid-prune-type-cann","errorCode":null,"errorMessage":"error registering pruner: invalid prune type: cannot be empty","messagePattern":"error registering pruner: invalid prune type: cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/system/pruner/pruner.go","lineNumber":100,"sourceCode":"// registered holds a map of PruneFunc functions registered through [Register].\n// It is considered immutable after startup.\nvar registered map[ContentType]PruneFunc\n\n// Register registers a [PruneFunc] under the given name to be included in\n// \"docker system prune\". It is designed to be called in an init function\n// and is not safe for concurrent use.\n//\n// For example:\n//\n//\t func init() {\n//\t\t// Register the prune command to run as part of \"docker system prune\".\n//\t\tif err := prune.Register(prune.TypeImage, prunerFn); err != nil {\n//\t\t\tpanic(err)\n//\t\t}\n//\t}\nfunc Register(name ContentType, pruneFunc PruneFunc) error {\n\tif name == \"\" {\n\t\treturn errors.New(\"error registering pruner: invalid prune type: cannot be empty\")\n\t}\n\tif pruneFunc == nil {\n\t\treturn errors.New(\"error registering pruner: prune function is nil for \" + string(name))\n\t}\n\tif registered == nil {\n\t\tregistered = make(map[ContentType]PruneFunc)\n\t}\n\tif _, exists := registered[name]; exists {\n\t\treturn fmt.Errorf(\"error registering pruner: content-type %s is already registered\", name)\n\t}\n\tregistered[name] = pruneFunc\n\treturn nil\n}\n\n// List iterates over all registered pruners, starting with known pruners\n// in their predefined order, followed by any others (sorted alphabetically).\nfunc List() iter.Seq2[ContentType, PruneFunc] {\n\tall := maps.Clone(registered)","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/docker/cli/blob/e9452d6e785f6e365712b9d71bd7517591773c86/cli/command/system/pruner/pruner.go#L82-L118","documentation":"Returned by pruner.Register when a pruner is registered with an empty ContentType name. Register is called from init() functions to add content types (images, containers, networks, volumes, build-cache) to `docker system prune`; an empty name would make the pruner unaddressable, so registration fails fast.","triggerScenarios":"Calling pruner.Register(\"\", fn) — i.e. code (typically an init() in a CLI package or a fork/extension of docker/cli) passing an empty ContentType constant at cli/command/system/pruner/pruner.go:100.","commonSituations":"Developers extending docker/cli with a custom pruner and forgetting to define the ContentType constant; refactors that leave a ContentType variable zero-valued. End users of the stock docker CLI should never see this — it indicates a programming error, and callers typically panic on it in init().","solutions":["Pass a non-empty ContentType when registering: define a constant like `const TypeFoo pruner.ContentType = \"foo\"` and use it.","Audit init() functions in your fork/plugin for Register calls with uninitialized ContentType values."],"exampleFix":"// before\nfunc init() {\n    if err := pruner.Register(\"\", pruneFn); err != nil { panic(err) }\n}\n// after\nconst TypeWidget pruner.ContentType = \"widget\"\nfunc init() {\n    if err := pruner.Register(TypeWidget, pruneFn); err != nil { panic(err) }\n}","handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":["docker-cli","pruner","registration","developer-error"],"analyzedSha":"e9452d6e785f6e365712b9d71bd7517591773c86","analyzedAt":"2026-08-01T07:09:22.474Z","schemaVersion":2}