hyperledger/fabric · error
malformed signature metadata
Error message
malformed signature metadata
What it means
This error is returned by verifySignatureIsBoundToProposal in the SmartBFT verifier when the SIGNATURES entry of a block's metadata cannot be unmarshalled into a cb.Metadata protobuf. It means the raw bytes at cb.BlockMetadataIndex_SIGNATURES are corrupt or were not produced by a Hyperledger Fabric orderer. The error wraps the underlying proto.Unmarshal error.
Source
Thrown at orderer/consensus/smartbft/verifier.go:428
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 err
}
// Ensure Metadata slice is of the right size
if len(block.Metadata.Metadata) != len(cb.BlockMetadataIndex_name) {
return errors.Errorf("block metadata is of size %d but should be of size %d",
len(block.Metadata.Metadata), len(cb.BlockMetadataIndex_name))
}
signatureMetadata := &cb.Metadata{}
if err := proto.Unmarshal(block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], signatureMetadata); err != nil {
return errors.Wrap(err, "malformed signature metadata")
}
ordererMDFromBlock := &cb.OrdererBlockMetadata{}
if err := proto.Unmarshal(signatureMetadata.Value, ordererMDFromBlock); err != nil {
return errors.Wrap(err, "malformed orderer metadata in block")
}
// Ensure the block's OrdererBlockMetadata matches the signature.
if !proto.Equal(ordererMDFromBlock, ordererMD) {
return errors.Errorf("signature's OrdererBlockMetadata and OrdererBlockMetadata extracted from block do not match")
}
return nil
}
type consenterVerifier struct {
logger *flogging.FabricLogger
channel stringView on GitHub (pinned to 2736b63f8f)
Solutions
- Regenerate the block from a trusted source (configtxgen / orderer genesis) rather than repairing bytes
- Verify ledger storage integrity; restore from backup or re-fetch blocks from other orderers
- Check that all orderers run compatible Fabric versions producing the same metadata layout
- Log and inspect the wrapped proto error to confirm the exact unmarshal failure
Example fix
// before: trusting bytes read from an external file
md := readBlockFromFile("block.bin")
err := verifier.VerifyConsenterSig(md, sig)
// after: validate metadata before verification
sigMD := &cb.Metadata{}
if err := proto.Unmarshal(md.Metadata[cb.BlockMetadataIndex_SIGNATURES], sigMD); err != nil {
return fmt.Errorf("skipping corrupt block: %w", err)
}
err = verifier.VerifyConsenterSig(md, sig) Defensive patterns
Strategy: validation
Validate before calling
if blk == nil || blk.Metadata == nil || len(blk.Metadata.Metadata) <= int(cb.BlockMetadataIndex_SIGNATURES) {
return errors.New("block lacks SIGNATURES metadata")
}
probe := &cb.Metadata{}
if err := proto.Unmarshal(blk.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], probe); err != nil {
return fmt.Errorf("invalid signature metadata: %w", err)
} Type guard
func hasSignatureMetadata(b *cb.Block) bool {
return b != nil && b.Metadata != nil && len(b.Metadata.Metadata) > int(cb.BlockMetadataIndex_SIGNATURES)
} Try / catch
defer func() {
if r := recover(); r != nil { log.Printf("block verification panicked: %v", r) }
}()
if err := verifier.VerifyConsenterSig(blk, sig); err != nil {
if strings.Contains(err.Error(), "malformed signature metadata") {
log.Warnf("corrupt block %d: %v", blk.Header.Number, err)
return errSkipBlock
}
return err
} Prevention
- Only feed blocks from trusted orderer/ledger write paths into the verifier
- Validate block structure (metadata presence and unmarshallability) before verification
- Keep all orderer nodes on the same compatible Fabric version
- Monitor ledger storage health; restore from backup on corruption
When it happens
Trigger: VerifyConsenterSig is called on a block whose Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES] contains bytes that are not a valid serialized cb.Metadata message (truncated, corrupted, or random bytes).
Common situations: Blocks written by non-Fabric or modified tooling; corrupted ledger files after disk issues; manual block surgery during testing; version skew where the metadata layout changed; replaying hand-crafted blocks into the verifier.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed unmarshalling OrdererBlockMetadata
- expected metadata in block to be [view_id:%d latest_sequence
- malformed orderer metadata in block
- failed to unmarshal BFT metadata configuration
- failed to marshal request envelope: proto: Marshal called wi
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/2b1927720f8a3923.
Report an issue: GitHub.