hyperledger/fabric · error
missing signature header
Error message
missing signature header
What it means
checkACL requires a non-nil SignatureHeader to identify the requester and verify their signature. When the signature header inside the snapshot request is nil, the service cannot even attempt ACL validation and returns 'missing signature header' immediately.
Source
Thrown at core/ledger/snapshotgrpc/snapshot_service.go:112
return nil, err
}
lgr, err := s.getLedger(query.ChannelId)
if err != nil {
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
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Populate SignatureHeader (creator identity + channel ID) before marshaling and signing the request.
- Use protoutil's signature-header helpers to build it consistently.
- Verify the unmarshaled request actually contains the header after round-tripping through your transport.
- Check client SDK version for regressions in header construction.
Example fix
// before
req := &pb.SnapshotRequest{ChannelId: chID}
// after
req := &pb.SnapshotRequest{ChannelId: chID, SignatureHeader: protoutil.NewSignatureHeader(signer)} Defensive patterns
Strategy: validation
Validate before calling
if req.GetSignatureHeader() == nil {
return fmt.Errorf("refusing to submit: SignatureHeader is nil")
}
raw, _ := proto.Marshal(req)
signedReq := &pb.SignedSnapshotRequest{Request: raw, Signature: sig}
err := svc.Generate(ctx, signedReq) Type guard
func hasSignatureHeader(r *pb.SnapshotRequest) bool {
return r != nil && r.GetSignatureHeader() != nil && len(r.GetSignatureHeader().Creator) > 0
} Try / catch
_, err := svc.Generate(ctx, signedReq)
if err != nil && strings.Contains(err.Error(), "missing signature header") {
// rebuild request with protoutil.NewSignatureHeader(signer) and re-sign
}
Prevention
- Always construct requests through a helper that sets SignatureHeader.
- Assert header presence after unmarshal round trips.
- Review SDK upgrade notes for changes to header construction APIs.
When it happens
Trigger: Submitting Generate/Cancel/QueryPendings with a request whose SnapshotRequest.SignatureHeader field is nil — an unpopulated creator/channel header — so checkACL receives signatureHdr == nil.
Common situations: Hand-built clients forgetting to populate SignatureHeader; marshaling a partially-initialized request that dropped the header; a client library upgrade changing header construction.
Related errors
- client identity expired
- failed to unmarshal snapshot request
- missing channel ID
- cannot find ledger for channel %s
- discovery service refused our Request
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/16ea469ef7c41e96.
Report an issue: GitHub.