grpc/grpc-go · info

credentials: rawConn is dispatched out of gRPC

Error message

credentials: rawConn is dispatched out of gRPC

What it means

ErrConnDispatched is a sentinel error (not a real failure) that a custom TransportCredentials implementation returns from ClientHandshake or ServerHandshake to signal that it has taken ownership of the underlying net.Conn and routed it outside of gRPC (e.g., to a proxy or in-process handler). gRPC checks for this exact error and, when seen, does NOT close the connection and does not treat it as a handshake failure.

Solutions

  1. If you are the credential author, ensure you return credentials.ErrConnDispatched (not a wrapped variant) so gRPC's exact-equality check (err == credentials.ErrConnDispatched) matches.
  2. If you see this in application-level error handling, treat it as non-fatal: do not retry or close the connection; gRPC already handles it.
  3. Use errors.Is or direct equality only if you are building transport-level code that inspects handshake results.

Example fix

// before
customConn, err := myProxy.Route(rawConn)
if err != nil { return nil, nil, fmt.Errorf("dispatch failed: %w", err) }
return nil, nil, errors.New("dispatched") // gRPC closes the conn
// after
customConn, err := myProxy.Route(rawConn)
if err != nil { return nil, nil, err }
return nil, nil, credentials.ErrConnDispatched // gRPC leaves conn open
Defensive patterns

Strategy: validation

Validate before calling

// If inspecting handshake results in transport-level code:
if err == credentials.ErrConnDispatched {
    // expected: conn was routed elsewhere, do not close
    return nil
}

Try / catch

// This is a sentinel, not a failure. Handle with direct equality:
if err == credentials.ErrConnDispatched || err == io.EOF {
    // normal control flow; do not treat as error
}

Prevention

When it happens

Trigger: A custom TransportCredentials.ServerHandshake or ClientHandshake implementation returns credentials.ErrConnDispatched after handing the raw net.Conn to a non-gRPC consumer (e.g., an HTTP/1 proxy, a TLS-termination sidecar, or an in-process listener). The error then propagates up through transport.NewServerTransport or grpc.Dial's connection setup.

Common situations: Developers writing custom proxy or connection-pooling credentials that intercept certain connections. Also seen with the internal proxyattributes package or custom listener wrappers that conditionally route traffic. The error is expected control flow, not a bug — but it surfaces in logs if not handled correctly.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/12055abafda736ab. Report an issue: GitHub.

Appendix: source

Thrown at credentials/credentials.go:148

}

// AuthorityValidator validates the authority used to override the `:authority`
// header. This is an optional interface that implementations of AuthInfo can
// implement if they support per-RPC authority overrides. It is invoked when the
// application attempts to override the HTTP/2 `:authority` header using the
// CallAuthority call option.
type AuthorityValidator interface {
	// ValidateAuthority checks the authority value used to override the
	// `:authority` header. The authority parameter is the override value
	// provided by the application via the CallAuthority option. This value
	// typically corresponds to the server hostname or endpoint the RPC is
	// targeting. It returns non-nil error if the validation fails.
	ValidateAuthority(authority string) error
}

// ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
// and the caller should not close rawConn.
var ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")

// TransportCredentials defines the common interface for all the live gRPC wire
// protocols and supported transport security protocols (e.g., TLS, SSL).
type TransportCredentials interface {
	// ClientHandshake does the authentication handshake specified by the
	// corresponding authentication protocol on rawConn for clients. It returns
	// the authenticated connection and the corresponding auth information
	// about the connection.  The auth information should embed CommonAuthInfo
	// to return additional information about the credentials. Implementations
	// must use the provided context to implement timely cancellation.  gRPC
	// will try to reconnect if the error returned is a temporary error
	// (io.EOF, context.DeadlineExceeded or err.Temporary() == true).  If the
	// returned error is a wrapper error, implementations should make sure that
	// the error implements Temporary() to have the correct retry behaviors.
	// Additionally, ClientHandshakeInfo data will be available via the context
	// passed to this call.
	//
	// The second argument to this method is the `:authority` header value used

View on GitHub (pinned to 0c51461d27)