hyperledger/fabric · error

failed extracting stream context

Error message

failed extracting stream context

What it means

GetTLSSessionBinding uses the gRPC peer package to pull authentication info from the incoming stream context. If the context carries no peer (peer.FromContext fails), there is no TLS session to derive keying material from, so the function aborts with this error. It guards the contract that a bound request must arrive over an authenticated gRPC stream.

Source

Thrown at orderer/common/cluster/util.go:701

		return nil, errors.Wrap(err, "failed generating TLS Binding material")
	}
	return tlsBinding, nil
}

func GetSessionBindingHash(authReq *orderer.NodeAuthRequest) []byte {
	return util.ComputeSHA256(util.ConcatenateBytes(
		[]byte(strconv.FormatUint(uint64(authReq.Version), 10)),
		EncodeTimestamp(authReq.Timestamp),
		[]byte(strconv.FormatUint(authReq.FromId, 10)),
		[]byte(strconv.FormatUint(authReq.ToId, 10)),
		[]byte(authReq.Channel),
	))
}

func GetTLSSessionBinding(ctx context.Context, bindingPayload []byte) ([]byte, error) {
	peerInfo, ok := peer.FromContext(ctx)
	if !ok {
		return nil, errors.New("failed extracting stream context")
	}
	connState := peerInfo.AuthInfo.(credentials.TLSInfo).State

	tlsBinding, err := exportKM(connState, KeyingMaterialLabel, bindingPayload)
	if err != nil {
		return nil, errors.Wrap(err, "failed exporting keying material")
	}

	return tlsBinding, nil
}

func VerifySignature(identity, msgHash, signature []byte) error {
	block, _ := pem.Decode(identity)
	if block == nil {
		return errors.New("pem decoding failed")
	}

	cert, err := x509.ParseCertificate(block.Bytes)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the caller passes the ctx received from the gRPC stream handler (grpc.StreamServerInfo / ServerStream.Context()) rather than a synthesized context
  2. Configure TLS on both sides of the gRPC channel so the server populates peer.AuthInfo (credentials.TLSInfo)
  3. Verify the call path actually goes through the gRPC transport; a locally invoked function will have no peer
  4. In tests, use credentials of a real in-process gRPC server (bufconn with TLS) or inject a peer.NewContext-wrapped context

Example fix

// before
tlsBinding, err := cluster.GetTLSSessionBinding(context.Background(), payload)
// after
func (s *srv) Req(stream cluster.Stream) error {
    ctx := stream.Context() // context from the authenticated gRPC stream
    tlsBinding, err := cluster.GetTLSSessionBinding(ctx, payload)
    ...
}
Defensive patterns

Strategy: type-guard

Validate before calling

_, ok := peer.FromContext(ctx)
if !ok { return errors.New("no gRPC peer in context; cannot export TLS binding") }

Type guard

func hasPeerContext(ctx context.Context) bool {
    pi, ok := peer.FromContext(ctx)
    return ok && pi != nil && pi.AuthInfo != nil
}

Try / catch

binding, err := cluster.GetTLSSessionBinding(ctx, payload)
if err != nil {
    if strings.Contains(err.Error(), "failed extracting stream context") {
        // fall back or reject the request: context has no authenticated peer
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetTLSSessionBinding with a ctx that was not obtained from a real gRPC stream handler: a manually constructed context.Context, a context from a non-TLS/insecure gRPC connection, or a test harness that passes context.Background().

Common situations: Unit tests invoking the binding logic without a gRPC server; clients connecting over plaintext (no TLS credentials configured so peer.AuthInfo is absent); middleware that forwards a stripped context instead of the stream's context.

Related errors


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