{"record":{"id":"5c5efe13a1ab0f94","repo":"docker/cli","slug":"container-name-cannot-be-empty","errorCode":null,"errorMessage":"container name cannot be empty","messagePattern":"container name cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/container/rm.go","lineNumber":77,"sourceCode":"\tflags.BoolVarP(&opts.force, \"force\", \"f\", false, \"Force the removal of a running container (uses SIGKILL)\")\n\treturn cmd\n}\n\n// newRemoveCommand adds subcommands for \"docker container\"; unlike the\n// top-level \"docker rm\", it also adds a \"remove\" alias to support\n// \"docker container remove\" in addition to \"docker container rm\".\nfunc newRemoveCommand(dockerCli command.Cli) *cobra.Command {\n\tcmd := *newRmCommand(dockerCli)\n\tcmd.Aliases = []string{\"rm\", \"remove\"}\n\treturn &cmd\n}\n\nfunc runRm(ctx context.Context, dockerCLI command.Cli, opts *rmOptions) error {\n\tapiClient := dockerCLI.Client()\n\terrChan := parallelOperation(ctx, opts.containers, func(ctx context.Context, ctrID string) error {\n\t\tctrID = strings.Trim(ctrID, \"/\")\n\t\tif ctrID == \"\" {\n\t\t\treturn errors.New(\"container name cannot be empty\")\n\t\t}\n\t\t_, err := apiClient.ContainerRemove(ctx, ctrID, client.ContainerRemoveOptions{\n\t\t\tRemoveVolumes: opts.rmVolumes,\n\t\t\tRemoveLinks:   opts.rmLink,\n\t\t\tForce:         opts.force,\n\t\t})\n\t\treturn err\n\t})\n\n\tvar errs []error\n\tfor _, name := range opts.containers {\n\t\tif err := <-errChan; err != nil {\n\t\t\tif opts.force && errdefs.IsNotFound(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\terrs = append(errs, err)\n\t\t\tcontinue\n\t\t}","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/container/rm.go#L59-L95","documentation":"Returned by runRm's per-container worker when, after strings.Trim(ctrID, \"/\"), the container identifier is empty. This catches arguments that were only slashes (e.g. '//') or expanded to nothing, preventing an empty ID being sent to the daemon's remove API.","triggerScenarios":"`docker rm ''`, `docker rm //`, or a variable that expands to empty/slashes. parallelOperation runs each arg through the trim; an all-slash arg becomes empty.","commonSituations":"Unset shell variable: `docker rm \"$CID\"` with CID empty. Looping over a list with a trailing empty element. JSON/YAML parsing producing empty container names. Misconfigured cleanup scripts.","solutions":["Ensure the container name/ID argument is non-empty before calling docker rm.","Guard the variable: `CID=${CID:?container id required}` or skip empty entries in loops.","Sanitize inputs from config files (strip blanks) before passing to docker rm."],"exampleFix":"// before\nfor c in \"$@\"; do docker rm \"$c\"; done   # $@ contains ''\n\n// after\nfor c in \"$@\"; do [ -n \"$c\" ] && docker rm \"$c\"; done","handlingStrategy":"validation","validationCode":"func validContainerID(id string) error {\n    if strings.TrimSpace(strings.Trim(id, \"/\")) == \"\" {\n        return errors.New(\"container name cannot be empty\")\n    }\n    return nil\n}\n\nfor _, c := range containers {\n    if err := validContainerID(c); err != nil {\n        return err\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Skip empty entries when looping: `for c in \"$@\"; do [ -n \"$c\" ] || continue; docker rm \"$c\"; done`.","Fail fast on unset vars: `set -u` and `${VAR:?required}`.","Sanitize config-derived container lists by stripping blanks."],"tags":["validation","empty-value","container","remove"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}