docker/cli · error

invalid option for flag --resolve-image

Error message

invalid option %s for flag --resolve-image

What it means

Raised by runDeploy when the --resolve-image flag value is not one of the three allowed constants: always, changed, or never. This flag controls whether/how the registry is queried to resolve image digests during stack deploy.

Solutions

  1. Use exactly one of: --resolve-image=always, --resolve-image=changed, or --resolve-image=never.
  2. If sourcing the value from a variable, validate it against the allowed set before invoking deploy.
  3. Check the Docker CLI version docs to confirm the option set hasn't changed.

Example fix

// before
docker stack deploy --resolve-image allways mystack -c compose.yml
// after
docker stack deploy --resolve-image always mystack -c compose.yml
Defensive patterns

Strategy: validation

Validate before calling

var validResolveImage = map[string]struct{}{"always": {}, "changed": {}, "never": {}}

func resolveImageOpt(v string) error {
    if _, ok := validResolveImage[v]; !ok {
        return fmt.Errorf("invalid --resolve-image value %q; want always|changed|never", v)
    }
    return nil
}

Type guard

type ResolveImage string

const (
    ResolveAlways  ResolveImage = "always"
    ResolveChanged ResolveImage = "changed"
    ResolveNever   ResolveImage = "never"
)

func (r ResolveImage) Valid() bool {
    switch r {
    case ResolveAlways, ResolveChanged, ResolveNever:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Running `docker stack deploy --resolve-image <value>` where <value> is anything other than 'always', 'changed', or 'never'. The switch at deploy.go:82 falls through to the default branch. This typically happens only with typos or direct API/library calls since cobra flag validation usually catches it earlier.

Common situations: Typo like 'allways', 'chagned', 'true', or 'on'; passing a value sourced from a config/env var without validation; older docs referencing a removed/renamed option.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/093efde16d2b9771. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/stack/deploy.go:86

	return cmd
}

// Resolve image constants
const (
	resolveImageAlways  = "always"
	resolveImageChanged = "changed"
	resolveImageNever   = "never"
)

const defaultNetworkDriver = "overlay"

// runDeploy is the swarm implementation of docker stack deploy
func runDeploy(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, opts *deployOptions, cfg *composetypes.Config) error {
	switch opts.resolveImage {
	case resolveImageAlways, resolveImageChanged, resolveImageNever:
		// valid options.
	default:
		return fmt.Errorf("invalid option %s for flag --resolve-image", opts.resolveImage)
	}

	if opts.detach && !flags.Changed("detach") {
		_, _ = fmt.Fprintln(dockerCLI.Err(), "Since --detach=false was not specified, tasks will be created in the background.\n"+
			"In a future release, --detach=false will become the default.")
	}

	return deployCompose(ctx, dockerCLI, opts, cfg)
}

// checkDaemonIsSwarmManager does an Info API call to verify that the daemon is
// a swarm manager. This is necessary because we must create networks before we
// create services, but the API call for creating a network does not return a
// proper status code when it can't create a network in the "global" scope.
func checkDaemonIsSwarmManager(ctx context.Context, dockerCli command.Cli) error {
	res, err := dockerCli.Client().Info(ctx, client.InfoOptions{})
	if err != nil {
		return err

View on GitHub (pinned to 4f84911bfe)