hyperledger/fabric · error
error unmarshalling signatures from metadata: %v
Error message
error unmarshalling signatures from metadata: %v
What it means
Within BlockSignatureVerifier, after confirming the SIGNATURES metadata entry exists, its bytes are proto-unmarshalled into cb.Metadata. Failure produces this wrapped error, meaning the signature entry bytes are corrupt or not a valid Metadata message containing Value and Signatures.
Source
Thrown at protoutil/blockutils.go:259
type BlockVerifierFunc func(header *cb.BlockHeader, metadata *cb.BlockMetadata) error
//go:generate counterfeiter -o mocks/policy.go --fake-name Policy . policy
type policy interface { // copied from common.policies to avoid circular import.
// EvaluateSignedData takes a set of SignedData and evaluates whether
// 1) the signatures are valid over the related message
// 2) the signing identities satisfy the policy
EvaluateSignedData(signatureSet []*SignedData) error
}
func BlockSignatureVerifier(bftEnabled bool, consenters []*cb.Consenter, policy policy) BlockVerifierFunc {
return func(header *cb.BlockHeader, metadata *cb.BlockMetadata) error {
if len(metadata.GetMetadata()) < int(cb.BlockMetadataIndex_SIGNATURES)+1 {
return errors.Errorf("no signatures in block metadata")
}
md := &cb.Metadata{}
if err := proto.Unmarshal(metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], md); err != nil {
return errors.Wrapf(err, "error unmarshalling signatures from metadata: %v", err)
}
var signatureSet []*SignedData
for _, metadataSignature := range md.Signatures {
var signerIdentity []byte
var signedPayload []byte
// if the SignatureHeader is empty and the IdentifierHeader is present, then the consenter expects us to fetch its identity by its numeric identifier
if bftEnabled && len(metadataSignature.GetSignatureHeader()) == 0 && len(metadataSignature.GetIdentifierHeader()) > 0 {
identifierHeader, err := UnmarshalIdentifierHeader(metadataSignature.IdentifierHeader)
if err != nil {
return fmt.Errorf("failed unmarshalling identifier header for block %d: %v", header.GetNumber(), err)
}
identifier := identifierHeader.GetIdentifier()
signerIdentity = searchConsenterIdentityByID(consenters, identifier)
if len(signerIdentity) == 0 {
// The identifier is not within the consenter set
continue
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Re-fetch the block from a trusted ordering node
- Verify the metadata index actually holds a serialized cb.Metadata (starts with valid protobuf field tags)
- If corruption recurs, rebuild the ledger or restore from backup
- Ensure all Fabric components run compatible versions so metadata layout matches
Example fix
// before
md := &cb.Metadata{}
if err := proto.Unmarshal(metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], md); err != nil {
return errors.Wrapf(err, "error unmarshalling signatures from metadata: %v", err)
}
// after
md := &cb.Metadata{}
raw := metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES]
if err := proto.Unmarshal(raw, md); err != nil {
return errors.Wrapf(err, "block %d: signatures metadata (%d bytes) is not valid protobuf", header.GetNumber(), len(raw))
} Defensive patterns
Strategy: validation
Validate before calling
raw := metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES]
probe := &cb.Metadata{}
if len(raw) == 0 || proto.Unmarshal(raw, probe) != nil {
return errors.New("signature metadata not parseable; re-fetch block")
} Type guard
func isParseableSignatureMetadata(raw []byte) (*cb.Metadata, bool) {
m := &cb.Metadata{}
if len(raw) == 0 || proto.Unmarshal(raw, m) != nil {
return nil, false
}
return m, true
} Try / catch
if err := verifier(header, metadata); err != nil {
logger.Warnf("signature metadata unparseable for block %d: %v", header.GetNumber(), err)
return refetchAndVerify(header.GetNumber())
} Prevention
- Detect recurring failures as signs of ledger/gossip corruption
- Verify metadata indices against the producing Fabric version
- Re-fetch blocks from trusted orderers before retrying verification
- Keep block payloads intact during transport (checksum on delivery)
When it happens
Trigger: Calling BlockSignatureVerifier's returned func on a block whose Metadata[BlockMetadataIndex_SIGNATURES] bytes fail proto.Unmarshal — corrupt ledger data, wrong index contents, or bytes not produced by the ordering service.
Common situations: Reading blocks from an unreliable peer/gossip path, truncated file-ledger segments, or custom block generators writing raw bytes into the signatures slot.
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.
Related errors
- error unmarshalling
- error unmarshalling original config
- error unmarshalling updated config
- Error unmarshalling to SignaturePolicy: %s
- failed to deserialize values
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/33382d308987d375.
Report an issue: GitHub.