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

  1. Populate SignatureHeader (creator identity + channel ID) before marshaling and signing the request.
  2. Use protoutil's signature-header helpers to build it consistently.
  3. Verify the unmarshaled request actually contains the header after round-tripping through your transport.
  4. 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

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


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