hyperledger/fabric · error

session binding read failed

Error message

session binding read failed

What it means

VerifyAuthRequest derives the expected TLS session binding (a hash over binding fields computed from the gRPC stream context) via GetTLSSessionBinding and wraps any failure with 'session binding read failed'. It means the server could not compute or read the binding from the connection itself — typically because TLS handshake data is missing from the context.

Source

Thrown at orderer/common/cluster/clusterservice.go:132

		}
		if err != nil {
			return err
		}
		// Else, no error occurred, so we continue to the next iteration
	}
}

func (s *ClusterService) VerifyAuthRequest(stream orderer.ClusterNodeService_StepServer, request *orderer.ClusterNodeServiceStepRequest) (*orderer.NodeAuthRequest, error) {
	authReq := request.GetNodeAuthrequest()
	if authReq == nil {
		return nil, errors.New("invalid request object")
	}

	bindingFieldsHash := GetSessionBindingHash(authReq)

	tlsBinding, err := GetTLSSessionBinding(stream.Context(), bindingFieldsHash)
	if err != nil {
		return nil, errors.Wrap(err, "session binding read failed")
	}

	if !bytes.Equal(tlsBinding, authReq.SessionBinding) {
		return nil, errors.New("session binding mismatch")
	}

	msg, err := asn1.Marshal(AuthRequestSignature{
		Version:        int64(authReq.Version),
		Timestamp:      EncodeTimestamp(authReq.Timestamp),
		FromId:         strconv.FormatUint(authReq.FromId, 10),
		ToId:           strconv.FormatUint(authReq.ToId, 10),
		SessionBinding: tlsBinding,
		Channel:        authReq.Channel,
	})
	if err != nil {
		return nil, errors.Wrap(err, "ASN encoding failed")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Enable mutual TLS on the orderer (General.TLS.Enabled: true) and require client certs, so the binding can be computed from the session.
  2. Remove any TLS-terminating proxy in front of ordering nodes, or switch to TLS passthrough.
  3. Verify the client presents a valid TLS certificate and that CA trust is configured on both sides.
  4. Inspect GetTLSSessionBinding / the wrapped underlying error in the orderer logs to identify exactly which binding field is missing.

Example fix

# before
General:
  TLS:
    Enabled: false
# after
General:
  TLS:
    Enabled: true
    PrivateKey: /path/tls/server.key
    Certificate: /path/tls/server.crt
    RootCAs: [/path/tls/ca.crt]
    ClientRootCAs: [/path/tls/ca.crt]
Defensive patterns

Strategy: try-catch

Validate before calling

// client side: confirm mTLS is configured before connecting
if tlsConfig == nil || len(tlsConfig.Certificates) == 0 {
    return errors.New("cluster connections require mutual TLS with a client certificate")
}

Try / catch

authReq, err := svc.VerifyAuthRequest(stream, request)
if err != nil {
    var wrapped interface{ Unwrap() error }
    if errors.As(err, &wrapped) && strings.Contains(err.Error(), "session binding read failed") {
        // underlying GetTLSSessionBinding error is wrapped — log it and check TLS setup
    }
    return err
}

Prevention

When it happens

Trigger: The Step stream arrives without mutual TLS (TLS disabled on the listener or the client not presenting a certificate), so GetTLSSessionBinding cannot extract the required handshake material.

Common situations: Orderer or cluster communication deployed without TLS while node authentication requires it; test environments disabling TLS; misconfigured General.TLS settings; a terminating proxy that ends TLS before the orderer, removing the session binding data.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/8c48b6ce3426080e. Report an issue: GitHub.