docker/cli · warning

plugin upgrade has been cancelled

Error message

plugin upgrade has been cancelled

What it means

Returned as a cancelledErr (implementing the Cancelled() marker) from runUpgrade when the remote plugin image differs from the currently installed one and the user declines the 'Plugin images do not match, are you sure?' confirmation prompt. This is an intentional cancellation, not a failure.

Solutions

  1. If you intended to upgrade, answer 'y' or pass --skip-remote-check to bypass the mismatch prompt.
  2. Treat the cancellation exit code as expected in automation.
  3. Verify the target image reference matches your intent before re-running.

Example fix

# before
docker plugin upgrade foo other/image:tag   # then type n
# after
docker plugin upgrade --skip-remote-check foo other/image:tag
Defensive patterns

Strategy: try-catch

Validate before calling

// Bypass the mismatch prompt when you are sure of the target image
// by passing --skip-remote-check

Try / catch

// Treat cancellation as non-fatal in automation
err := runUpgrade(ctx, cli, opts)
if err != nil {
    var c cancelledErr
    if errors.As(err, &c) { return nil }
    return err
}

Prevention

When it happens

Trigger: Running 'docker plugin upgrade foo newimage:tag' where newimage differs from the current reference, then answering 'n' at the confirmation prompt (lines 71-78 of upgrade.go).

Common situations: Operator aborting an upgrade after noticing the image mismatch; scripts prompting interactively; fat-fingering 'n'.

Related errors


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

Appendix: source

Thrown at cli/command/plugin/upgrade.go:77

	if err != nil {
		return fmt.Errorf("error parsing remote upgrade image reference: %w", err)
	}
	remote = reference.TagNameOnly(remote)

	old, err := reference.ParseNormalizedNamed(res.Plugin.PluginReference)
	if err != nil {
		return fmt.Errorf("error parsing current image reference: %w", err)
	}
	old = reference.TagNameOnly(old)

	_, _ = fmt.Fprintf(dockerCLI.Out(), "Upgrading plugin %s from %s to %s\n", res.Plugin.Name, reference.FamiliarString(old), reference.FamiliarString(remote))
	if !opts.skipRemoteCheck && remote.String() != old.String() {
		r, err := prompt.Confirm(ctx, dockerCLI.In(), dockerCLI.Out(), "Plugin images do not match, are you sure?")
		if err != nil {
			return err
		}
		if !r {
			return cancelledErr{errors.New("plugin upgrade has been cancelled")}
		}
	}

	options, err := buildPullConfig(dockerCLI, opts)
	if err != nil {
		return err
	}

	responseBody, err := dockerCLI.Client().PluginUpgrade(ctx, opts.localName, client.PluginUpgradeOptions(options))
	if err != nil {
		return err
	}
	defer func() {
		_ = responseBody.Close()
	}()
	if err := jsonstream.Display(ctx, responseBody, dockerCLI.Out()); err != nil {
		return err
	}

View on GitHub (pinned to 4f84911bfe)