hyperledger/fabric · error

client identity expired

Error message

client identity expired

What it means

checkACL extracts the creator from the SignatureHeader and checks its certificate's expiration via crypto.ExpiresAt. If the identity has an expiration timestamp and that time is in the past, the request is rejected with 'client identity expired' before the ACL policy is evaluated.

Source

Thrown at core/ledger/snapshotgrpc/snapshot_service.go:117

		return nil, err
	}

	result, err := lgr.PendingSnapshotRequests()
	if err != nil {
		return nil, err
	}

	return &pb.QueryPendingSnapshotsResponse{BlockNumbers: result}, nil
}

func (s *SnapshotService) checkACL(resName string, signatureHdr *cb.SignatureHeader, signedRequest *pb.SignedSnapshotRequest) error {
	if signatureHdr == nil {
		return errors.New("missing signature header")
	}

	expirationTime := crypto.ExpiresAt(signatureHdr.Creator)
	if !expirationTime.IsZero() && time.Now().After(expirationTime) {
		return errors.New("client identity expired")
	}

	if err := s.ACLProvider.CheckACLNoChannel(
		resName,
		[]*protoutil.SignedData{{
			Identity:  signatureHdr.Creator,
			Data:      signedRequest.Request,
			Signature: signedRequest.Signature,
		}},
	); err != nil {
		return err
	}

	return nil
}

func (s *SnapshotService) getLedger(channelID string) (ledger.PeerLedger, error) {
	if channelID == "" {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Renew the client's enrollment certificate from the CA (fabric-ca enroll again) and rebuild the request.
  2. Verify node clock skew — a badly skewed clock can flag a valid cert as expired.
  3. Update MSP/certificates across the network per the Fabric operational guide after CA rotation.
  4. Re-sign the request with the fresh identity rather than reusing cached signed payloads.

Example fix

// before
signer := loadSigner("expired-cert.pem")
// after
signer := loadSigner("renewed-cert.pem") // re-enrolled via fabric-ca; check crypto.ExpiresAt(hdr.Creator)
Defensive patterns

Strategy: validation

Validate before calling

hdr := req.GetSignatureHeader()
if hdr != nil {
    if exp := crypto.ExpiresAt(hdr.Creator); !exp.IsZero() && time.Now().After(exp) {
        return fmt.Errorf("identity expired at %s; re-enroll before submitting", exp)
    }
}

Type guard

func identityValid(hdr *cb.SignatureHeader) bool {
    exp := crypto.ExpiresAt(hdr.GetCreator())
    return exp.IsZero() || time.Now().Before(exp)
}

Try / catch

_, err := svc.Generate(ctx, signedReq)
if err != nil && strings.Contains(err.Error(), "client identity expired") {
    return reenrollAndRetry(ctx, signedReq) // fabric-ca re-enroll, rebuild & re-sign request
}
return err

Prevention

When it happens

Trigger: Any snapshot request (Generate/Cancel/QueryPendings) signed by an identity whose x509 certificate expiry has passed, or a header whose Creator cert carries an expired/notAfter field.

Common situations: Long-running clients whose enrollment certificates expired (Fabric default 1-year certs); peers/clients not rotated after CA certificate renewal; offline signatures assembled long ago and replayed after expiry.

Related errors


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