docker/compose · error

invalid value for --rmi: %q

Error message

invalid value for --rmi: %q

What it means

The `--rmi` flag on `docker compose down` accepts only `all` or `local`. The PreRunE guard rejects any other non-empty value with this error, echoing the offending string.

Source

Thrown at cmd/compose/down.go:55

	removeOrphans bool
	timeChanged   bool
	timeout       int
	volumes       bool
	images        string
}

func downCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *BackendOptions) *cobra.Command {
	opts := downOptions{
		ProjectOptions: p,
	}
	downCmd := &cobra.Command{
		Use:   "down [OPTIONS] [SERVICES]",
		Short: "Stop and remove containers, networks",
		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
			opts.timeChanged = cmd.Flags().Changed("timeout")
			if opts.images != "" {
				if opts.images != "all" && opts.images != "local" {
					return fmt.Errorf("invalid value for --rmi: %q", opts.images)
				}
			}
			return nil
		}),
		RunE: Adapt(func(ctx context.Context, args []string) error {
			return runDown(ctx, dockerCli, backendOptions, opts, args)
		}),
		ValidArgsFunction: completeServiceNames(dockerCli, p),
	}
	flags := downCmd.Flags()
	removeOrphans := utils.StringToBool(os.Getenv(ComposeRemoveOrphans))
	flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file")
	flags.IntVarP(&opts.timeout, "timeout", "t", 0, "Specify a shutdown timeout in seconds")
	flags.BoolVarP(&opts.volumes, "volumes", "v", false, `Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers`)
	flags.StringVar(&opts.images, "rmi", "", `Remove images used by services. "local" remove only images that don't have a custom tag ("local"|"all")`)
	flags.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
		if name == "volume" {
			name = "volumes"

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Use `--rmi all` (remove all images used by the project) or `--rmi local` (only images without a custom tag).
  2. Omit `--rmi` entirely if no image removal is wanted — there is no 'none' value.
  3. Guard script variables: only append `--rmi` when its value is exactly `all` or `local`.

Example fix

# before
docker compose down --rmi always

# after
docker compose down --rmi all
Defensive patterns

Strategy: validation

Validate before calling

# bash
RMI_ARGS=()
case "${RMI:-}" in "") ;; all|local) RMI_ARGS=(--rmi "$RMI");; *) echo "--rmi must be all|local" >&2; exit 2;; esac
docker compose down "${RMI_ARGS[@]}"

Prevention

When it happens

Trigger: Running `docker compose down --rmi always` (thinking it mirrors pull policy wording), `--rmi none`, or `--rmi ${FLAG}` with an empty/typo variable value.

Common situations: Confusion with `docker image rm` semantics or with `--pull always` phrasing; CI teardown scripts forwarding an unvalidated variable to --rmi.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/190dc3c56bd91774. Report an issue: GitHub.