containerd/containerd · error

hybrid vsock handshake response error: %s

Error message

hybrid vsock handshake response error: %s

What it means

In the hybrid vsock dialer (hvsock), after dialing the host-side unix socket the client writes 'CONNECT <port>' and reads a line back; if the response does not contain "OK", this error is returned. It means the hvsock proxy on the other end explicitly rejected or answered unexpectedly to the handshake.

Source

Thrown at pkg/shim/util_unix.go:222

		if err != nil {
			return nil, err
		}
		if _, err = fmt.Fprintln(conn, "CONNECT", port); err != nil {
			conn.Close()
			return nil, err
		}
		errChan := make(chan error, 1)
		go func() {
			reader := bufio.NewReader(conn)
			response, err := reader.ReadString('\n')
			if err != nil {
				errChan <- err
				return
			}
			if strings.Contains(response, "OK") {
				errChan <- nil
			} else {
				errChan <- fmt.Errorf("hybrid vsock handshake response error: %s", response)
			}
		}()
		select {
		case err = <-errChan:
			if err != nil {
				conn.Close()
				// When it is EOF, maybe the server side is not ready.
				if err == io.EOF {
					log.G(context.Background()).Warnf("Read hybrid vsock got EOF, server may not ready")
					time.Sleep(retryInterval)
					continue
				}
				return nil, err
			}
			return conn, nil
		case <-timeoutCh:
			conn.Close()
			return nil, fmt.Errorf("timeout waiting for hybrid vsocket handshake of %s:%d", addr, port)

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Check the response text embedded in the error for the proxy's rejection reason.
  2. Verify the hvsock port in the address matches the port the guest service is listening on.
  3. Ensure the guest-side service/shim is fully started, then retry the dial.
  4. Confirm the host hvsock proxy version is compatible with this client's CONNECT handshake.

Example fix

// before
conn, err := shim.AnonDialer("hvsock:///run/hvsock.sock:1234", time.Second)
// after: confirm guest listener, then use correct port
conn, err := shim.AnonDialer("hvsock:///run/hvsock.sock:1024", 5*time.Second)
Defensive patterns

Strategy: retry

Validate before calling

// Before dialing, verify the target hvsock port is expected:
// confirm the guest-side listener registered on `port` via your VM control plane,
// e.g. check shim process logs or the host hvsock proxy's registered ports.

Type guard

func isHandshakeRejection(err error) bool {
	return err != nil && strings.Contains(err.Error(), "hybrid vsock handshake response error")
}

Try / catch

conn, err := shim.AnonDialer(hvAddr, timeout)
if isHandshakeRejection(err) {
	// log response text from err, wait for guest service, then retry
	time.Sleep(backoff)
	conn, err = shim.AnonDialer(hvAddr, timeout)
}

Prevention

When it happens

Trigger: dialHybridVsock -> hybridVsockDialer connects to the hvsock bridge unix socket and receives a non-OK response line, e.g. when the requested vsock port is not registered on the host proxy, the guest service is not listening, or the proxy speaks an incompatible protocol.

Common situations: Connecting to a shim in a Hyper-V/hybrid-vsock setup before the guest-side listener started; wrong port in the hvsock address; mismatched or outdated host-side hvsock proxy version.

Understand the failure class

Related errors


AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02). Data as JSON: /api/errors/b1363faf8455e671. Report an issue: GitHub.