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
- Enable mutual TLS on the orderer (General.TLS.Enabled: true) and require client certs, so the binding can be computed from the session.
- Remove any TLS-terminating proxy in front of ordering nodes, or switch to TLS passthrough.
- Verify the client presents a valid TLS certificate and that CA trust is configured on both sides.
- 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
- Enable mTLS on ordering nodes and require client certificates
- Use TLS passthrough, not termination, on any proxy in front of orderers
- Keep General.TLS settings consistent across the cluster
- Log the wrapped underlying error to identify the missing binding field
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
- invalid request object
- session binding mismatch
- failed to create new stream
- node %d doesn't exist in channel %s's membership
- invalid certificate DER
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/8c48b6ce3426080e.
Report an issue: GitHub.