hyperledger/fabric · error
bad payload
Error message
bad payload
What it means
After decoding the ByteBufferTuple from the proposal Payload, tuple.A is unmarshalled as the block's protobuf BlockData. This error means those bytes are not a valid common.BlockData protobuf message.
Source
Thrown at orderer/consensus/smartbft/signature.go:82
}
block.Header = &cb.BlockHeader{
Number: hdr.Number.Uint64(),
PreviousHash: hdr.PreviousHash,
DataHash: hdr.DataHash,
}
if len(proposal.Payload) == 0 {
return nil, errors.New("proposal payload cannot be nil")
}
tuple := &ByteBufferTuple{}
if err := tuple.FromBytes(proposal.Payload); err != nil {
return nil, errors.Wrap(err, "bad payload and metadata tuple")
}
if err := proto.Unmarshal(tuple.A, block.Data); err != nil {
return nil, errors.Wrap(err, "bad payload")
}
if err := proto.Unmarshal(tuple.B, block.Metadata); err != nil {
return nil, errors.Wrap(err, "bad metadata")
}
return block, nil
}
type asn1Header struct {
Number *big.Int
PreviousHash []byte
DataHash []byte
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify tuple field order: A must be the marshalled block Data, B the marshalled Metadata; swap if reversed.
- Discard the proposal and re-synchronize the channel from a healthy quorum of consenters.
- Confirm all nodes run a compatible Fabric version producing identical block encoding.
- Check storage medium integrity (fsck/SMART) if corruption recurs on the same node.
Example fix
// before
tuple := &ByteBufferTuple{A: metaBytes, B: dataBytes} // swapped
// after
tuple := &ByteBufferTuple{A: dataBytes, B: metaBytes} Defensive patterns
Strategy: validation
Validate before calling
tuple := &ByteBufferTuple{}
if err := tuple.FromBytes(prop.Payload); err != nil {
return err
}
bd := &common.BlockData{}
if err := proto.Unmarshal(tuple.A, bd); err != nil {
return fmt.Errorf("tuple.A is not BlockData: %v", err)
}
block, err := ProposalToBlock(prop) Type guard
func tupleAIsBlockData(p types.Proposal) bool {
t := &ByteBufferTuple{}
if t.FromBytes(p.Payload) != nil {
return false
}
return proto.Unmarshal(t.A, &common.BlockData{}) == nil
} Try / catch
block, err := ProposalToBlock(prop)
if err != nil && strings.HasPrefix(err.Error(), "bad payload") && !strings.Contains(err.Error(), "metadata") {
// block data corrupt: discard and resync
return resync()
} Prevention
- Keep tuple field order A=data, B=metadata; never swap.
- Round-trip test marshal/unmarshal of proposals in CI.
- Monitor storage for bit-rot (checksums) on ledger volumes.
- Refuse proposals that fail signature verification before decoding.
When it happens
Trigger: ProposalToBlock called where tuple.A of the decoded Payload is corrupt or not a marshalled BlockData — e.g. swapped tuple fields (data/metadata reversed), foreign protobuf bytes, or bit corruption in transit/storage.
Common situations: Hand-rolled proposal construction placing the wrong bytes in tuple.A; corrupted WAL/ledger records; a proposal relayed through non-Fabric tooling that re-encoded the bytes.
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
- failed to unmarshal BFT metadata configuration
- failed to marshal request envelope: proto: Marshal called wi
- invalid consensus type property in config: %v
- invalid options encoded in consensus metadata: %v
- bad metadata
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/5de9715846e6b547.
Report an issue: GitHub.