hyperledger/fabric · error
identity in signature header does not match expected identit
Error message
identity in signature header does not match expected identity
What it means
The IdentifierHeader inside a consenter signature must carry the same identity number as the identity that supposedly produced the signature (identityID, derived from the signature verification with the node's channel membership). This error means the signature's declared consenter ID does not match the identity that actually signed — a signature attributed to the wrong consenter, or a node using the wrong TLS/channel identity.
Source
Thrown at orderer/consensus/smartbft/verifier.go:399
// BlockHeader []byte
// OrdererBlockMetadata []byte
// Ensure block header is equal
if !bytes.Equal(prop.Header, sig.BlockHeader) {
v.Logger.Errorf("Expected block header %s but got %s", base64.StdEncoding.EncodeToString(prop.Header),
base64.StdEncoding.EncodeToString(sig.BlockHeader))
return errors.Errorf("mismatched block header")
}
// Ensure signature header matches the identity
sigHdr := &cb.IdentifierHeader{}
if err := proto.Unmarshal(sig.IdentifierHeader, sigHdr); err != nil {
return errors.Wrap(err, "malformed signature header")
}
if identityID != uint64(sigHdr.Identifier) {
v.Logger.Warnf("Expected identity %d but got %d", identityID,
sigHdr.Identifier)
return errors.Errorf("identity in signature header does not match expected identity")
}
// Ensure orderer block metadata's consenter MD matches the proposal
ordererMD := &cb.OrdererBlockMetadata{}
if err := proto.Unmarshal(sig.OrdererBlockMetadata, ordererMD); err != nil {
return errors.Wrap(err, "malformed orderer metadata in signature")
}
if !bytes.Equal(ordererMD.ConsenterMetadata, prop.Metadata) {
v.Logger.Warnf("Expected consenter metadata %s but got %s in proposal",
base64.StdEncoding.EncodeToString(ordererMD.ConsenterMetadata), base64.StdEncoding.EncodeToString(prop.Metadata))
return errors.Errorf("consenter metadata in OrdererBlockMetadata doesn't match proposal")
}
block, err := ProposalToBlock(prop)
if err != nil {
v.Logger.Warnf("got malformed proposal: %v", err)
return errView on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure all consenters have processed the latest channel config so identity-to-ID mappings agree, and restart nodes whose mapping is stale.
- Verify each ordering node's TLS certificates and local MSP match its configured consenter entry.
- Trigger a view change after any channel membership change so signatures are regenerated with correct identifiers.
- Check for membership churn (nodes added/removed) around the time of the error and re-verify the consenter list ordering.
Example fix
// before: mapping skew after membership change identityID = 3 (from cert); sigHdr.Identifier = 2 -> error // after: all nodes agree on identity mapping identityID = 3; sigHdr.Identifier = 3
Defensive patterns
Strategy: validation
Validate before calling
sigHdr := &cb.IdentifierHeader{}
if err := proto.Unmarshal(sig.IdentifierHeader, sigHdr); err != nil { return err }
if identityID != uint64(sigHdr.Identifier) {
// membership mapping is stale; refresh channel config before trusting signatures
return fmt.Errorf("identity %d != header id %d", identityID, sigHdr.Identifier)
} Try / catch
if err := verifySig(sig); err != nil && strings.Contains(err.Error(), "identity in signature header") {
refreshMembershipMapping()
return err
} Prevention
- Apply channel config updates atomically across all orderers
- Restart orderers after membership changes so identity mappings reload
- Audit TLS cert/MSP configuration against each consenter's channel entry
When it happens
Trigger: VerifyConsenterSig -> verifySignatureIsBoundToProposal: identityID != uint64(sigHdr.Identifier). Triggered when a signature arrives claiming to be from consenter N but its certificate/identity resolves to a different slot number, or the IdentifierHeader was built with a stale/wrong self ID.
Common situations: Consenter order changed in the channel config (e.g. a node removed/added) while another node cached the old identity-to-slot mapping; a node restarted with the wrong TLS keypair/certificate; configuration change not yet propagated to all nodes; a misbehaving node signing with another's ID.
Related errors
- malformed orderer metadata in signature
- consenter options type mismatch
- failed unmarshaling identity %s
- failed evaluating policy on signed data during check policy
- Could not serialize the signing identity: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/1ee263b9f2e670aa.
Report an issue: GitHub.