docker/cli · error

the raw stream connection does not implement halfCloser

Error message

the raw stream connection does not implement halfCloser

What it means

Raised by `docker system dial-stdio` when the connection returned by the API client's Dialer does not support half-close semantics (CloseRead/CloseWrite) and is not even a half-read/write-closer the CLI can wrap. dial-stdio proxies stdin/stdout to the raw Docker daemon stream and needs to close each direction independently, so a connection type without those methods cannot be used.

Source

Thrown at cli/command/system/dial_stdio.go:50

func runDialStdio(ctx context.Context, dockerCli command.Cli) error {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	dialer := dockerCli.Client().Dialer()
	conn, err := dialer(ctx)
	if err != nil {
		return fmt.Errorf("failed to open the raw stream connection: %w", err)
	}
	defer conn.Close()

	var connHalfCloser halfCloser
	switch t := conn.(type) {
	case halfCloser:
		connHalfCloser = t
	case halfReadWriteCloser:
		connHalfCloser = &nopCloseReader{t}
	default:
		return errors.New("the raw stream connection does not implement halfCloser")
	}

	stdin2conn := make(chan error, 1)
	conn2stdout := make(chan error, 1)
	go func() {
		stdin2conn <- copier(connHalfCloser, &halfReadCloserWrapper{os.Stdin}, "stdin to stream")
	}()
	go func() {
		conn2stdout <- copier(&halfWriteCloserWrapper{os.Stdout}, connHalfCloser, "stream to stdout")
	}()
	select {
	case err = <-stdin2conn:
		if err != nil {
			return err
		}
		// wait for stdout
		err = <-conn2stdout
	case err = <-conn2stdout:

View on GitHub (pinned to e9452d6e78)

Solutions

  1. Connect over a transport that supports half-close: unix socket (unix:///var/run/docker.sock) or plain tcp:// instead of a wrapped/proxied transport.
  2. If using ssh:// or a connection helper, update the docker CLI — half-close handling for wrapped connections has improved across versions.
  3. As a workaround, avoid dial-stdio by pointing the client directly at the daemon endpoint (set DOCKER_HOST) rather than tunneling through the CLI.

When it happens

Trigger: Running `docker system dial-stdio` when dockerCli.Client().Dialer() yields a net.Conn type that implements neither the halfCloser interface (CloseRead+CloseWrite) nor halfReadWriteCloser — e.g. certain tunneled, proxied, or custom transport connections (some TLS or exotic connection helpers) instead of a plain *net.TCPConn or *net.UnixConn.

Common situations: Using dial-stdio (often invoked implicitly by `docker -H ssh://...` or buildx/BuildKit clients) through a connection helper or proxy whose transport doesn't expose half-close; custom DOCKER_HOST transports; older/newer client-transport combinations changing the concrete conn type.

Related errors


AI-assisted analysis of docker/cli@e9452d6e78 (2026-08-01). Data as JSON: /data/errors/e9c24dd826e2a64d.json. Report an issue: GitHub.