{"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/e9452d6e785f6e365712b9d71bd7517591773c86/cli/command/container/rm.go#L59-L95","documentation":"Raised in runRm for `docker rm` when one of the container arguments, after trimming leading/trailing slashes, is an empty string. The CLI validates this client-side per container (removals run in parallel) so it fails fast instead of sending an empty ID to the ContainerRemove API.","triggerScenarios":"`docker rm \"\"`, `docker rm /` or `docker rm //` (slashes are trimmed to empty), or an argument list built from a variable/command substitution that yields an empty element, e.g. docker rm $ids where ids contains an empty entry.","commonSituations":"Shell scripts doing `docker rm $(docker ps -aq --filter ...)` where the subshell output is empty or contains blank lines quoted into empty args; xargs/loop pipelines passing empty strings; container names copied with a leading '/' from `docker inspect` plus nothing else.","solutions":["Guard script-generated arguments: only call docker rm when the ID list is non-empty (e.g. ids=$(docker ps -aq); [ -n \"$ids\" ] && docker rm $ids)","Filter blank lines before passing to docker rm, e.g. ... | grep . | xargs -r docker rm","Check for stray quoting that turns an empty variable into an explicit \"\" argument"],"exampleFix":"# before\ndocker rm \"$(docker ps -aq --filter status=exited)\"   # empty result -> docker rm \"\"\n# after\ndocker ps -aq --filter status=exited | xargs -r docker rm","handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":["docker-cli","container","rm","input-validation","shell-scripting"],"analyzedSha":"e9452d6e785f6e365712b9d71bd7517591773c86","analyzedAt":"2026-08-01T07:09:22.474Z","schemaVersion":2}