docker/cli · error

requires API version , but the Docker daemon API version is

Error message

%s requires API version %s, but the Docker daemon API version is %s

What it means

Thrown by areSubcommandsSupported() when the command (or any parent, walked up the cobra tree) has a `version` annotation whose required API version is greater than the daemon's actual API version (compared via versions.LessThan). It means the daemon is too old to support this subcommand.

Solutions

  1. Upgrade the Docker daemon on the target host so its API version >= the required version.
  2. Install an older CLI matching the daemon's API version (set DOCKER_API_VERSION to match and use a compatible CLI).
  3. Point DOCKER_HOST at a daemon that already meets the version requirement.

Example fix

# before
# daemon API 1.30, command requires 1.40
docker checkpoint ls
# after: upgrade dockerd, verify
sudo apt-get install --only-upgrade docker-ce
docker version  # Server Version >= required
DOCKER_API_VERSION=1.40 docker checkpoint ls
Defensive patterns

Strategy: validation

Validate before calling

// ensure CLI/daemon API compatibility before running
v, err := cli.ServerAPIVersion(ctx)
if err != nil { return err }
required, _ := versions.NewVersion("1.40")
actual, _ := versions.NewVersion(v)
if actual.LessThan(required) { return fmt.Errorf("daemon API %s too old", v) }

Prevention

When it happens

Trigger: Invoking a subcommand annotated with a minimum API version (e.g. `docker checkpoint`, `docker buildx`) against a daemon whose reported API version is lower than required.

Common situations: New CLI talking to an older daemon (version skew); pinned old dockerd on servers; remote DOCKER_HOST pointing at a stale node; downgrading the daemon but keeping a newer CLI.

Related errors


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

Appendix: source

Thrown at cmd/docker/docker.go:720

		// buildkit-specific flags are noop when buildkit is not enabled, so we do not add an error in that case
	})
	return errors.Join(errs...)
}

// Check recursively so that, e.g., `docker stack ls` returns the same output as `docker stack`
func areSubcommandsSupported(cmd *cobra.Command, details versionDetails) error {
	// Check recursively so that, e.g., `docker stack ls` returns the same output as `docker stack`
	for curr := cmd; curr != nil; curr = curr.Parent() {
		// Important: in the code below, calls to "details.CurrentVersion()" and
		// "details.ServerInfo()" are deliberately executed inline to make them
		// be executed "lazily". This is to prevent making a connection with the
		// daemon to perform a "ping" (even for commands that do not require a
		// daemon connection).
		//
		// See commit b39739123b845f872549e91be184cc583f5b387c for details.

		if cmdVersion, ok := curr.Annotations["version"]; ok && versions.LessThan(details.CurrentVersion(), cmdVersion) {
			return fmt.Errorf("%s requires API version %s, but the Docker daemon API version is %s", cmd.CommandPath(), cmdVersion, details.CurrentVersion())
		}
		if ost, ok := curr.Annotations["ostype"]; ok && details.ServerInfo().OSType != "" && ost != details.ServerInfo().OSType {
			return fmt.Errorf("%s is only supported on a Docker daemon running on %s, but the Docker daemon is running on %s", cmd.CommandPath(), ost, details.ServerInfo().OSType)
		}
		if _, ok := curr.Annotations["experimental"]; ok && !details.ServerInfo().HasExperimental {
			return fmt.Errorf("%s is only supported on a Docker daemon with experimental features enabled", cmd.CommandPath())
		}
	}
	return nil
}

func getFlagAnnotation(f *pflag.Flag, annotation string) string {
	if value, ok := f.Annotations[annotation]; ok && len(value) == 1 {
		return value[0]
	}
	return ""
}

View on GitHub (pinned to 4f84911bfe)