docker/cli · error
flag --use-api-socket can't be used with a Windows Docker…
Error message
flag --use-api-socket can't be used with a Windows Docker Engine
What it means
Returned when the experimental --use-api-socket flag is combined with a Docker Engine whose OSType is "windows" (create.go:253-255). The flag bind-mounts /var/run/docker.sock and injects credentials via a Linux path scheme, neither of which exists on a Windows engine. The check fires before any container-creation side effects.
Solutions
- Remove the --use-api-socket flag when targeting a Windows engine.
- Switch Docker Desktop / the daemon to Linux containers (Linux engine) before using --use-api-socket.
- If you need Docker API access inside a Windows container, manually bind the Windows named pipe (//./pipe/docker_engine) instead.
Example fix
// before docker run --use-api-socket myimage // after (on a Windows engine) docker run myimage
Defensive patterns
Strategy: validation
Validate before calling
// Before calling create/run with --use-api-socket, check the engine OS.
info, err := cli.Client().ServerInfo(ctx)
if err != nil { return err }
if opts.useAPISocket && info.OSType == "windows" {
return errors.New("--use-api-socket requires a Linux engine")
} Prevention
- Gate --use-api-socket behind a check of ServerInfo().OSType in wrapper scripts.
- Document that the flag is experimental and Linux-only.
- In CI, assert DOCKER_HOST targets a Linux engine before enabling the flag.
When it happens
Trigger: Running `docker run --use-api-socket <img>` or `docker create --use-api-socket <img>` while the connected daemon reports ServerInfo().OSType == "windows" (e.g. Docker Desktop on Windows targeting a Windows container engine, or DOCKER_HOST pointing at a Windows daemon).
Common situations: Switching Docker Desktop between Linux and Windows container modes and forgetting --use-api-socket is Linux-only; CI pipelines that set DOCKER_HOST to a remote Windows engine; scripts copied from a Linux dev box to a Windows host.
Related errors
- --pid: invalid PID mode
- --uts: invalid UTS mode
- --userns: invalid USER mode
- --cgroupns: invalid CGROUP mode
- --no-healthcheck conflicts with --health-* options
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/2144e91fe98ec219.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/container/create.go:254
ref, err := reference.ParseAnyReference(config.Image)
if err != nil {
return "", err
}
if named, ok := ref.(reference.Named); ok {
namedRef = reference.TagNameOnly(named)
}
const dockerConfigPathInContainer = "/run/secrets/docker/config.json"
var apiSocketCreds map[string]types.AuthConfig
if options.useAPISocket {
// We'll create two new mounts to handle this flag:
//
// 1. Mount the actual docker socket.
// 2. A synthesized ~/.docker/config.json with resolved tokens.
if dockerCLI.ServerInfo().OSType == "windows" {
return "", errors.New("flag --use-api-socket can't be used with a Windows Docker Engine")
}
// hard-code engine socket path until https://github.com/moby/moby/pull/43459 gives us a discovery mechanism
containerCfg.HostConfig.Mounts = append(containerCfg.HostConfig.Mounts, mount.Mount{
Type: mount.TypeBind,
Source: "/var/run/docker.sock",
Target: "/var/run/docker.sock",
BindOptions: &mount.BindOptions{},
})
/*
Ideally, we'd like to copy the config into a tmpfs but unfortunately,
the mounts won't be in place until we start the container. This can
leave around the config if the container doesn't get deleted.
We are using the most compose-secret-compatible approach,
which is implemented atView on GitHub (pinned to 4f84911bfe)