hyperledger/fabric · error
transaction %d has %d trailing bytes
Error message
transaction %d has %d trailing bytes
What it means
After re-marshaling, the canonical byte length must not be shorter than the raw transaction bytes; if it is, the raw entry contains trailing bytes appended after the valid Envelope. The library rejects such data because a block entry must be exactly one serialized Envelope — trailing bytes indicate corruption or tampering.
Source
Thrown at protoutil/blockutils.go:347
if err := proto.Unmarshal(rawTx, env); err != nil {
return fmt.Errorf("transaction %d is invalid: %v", i, err)
}
if len(env.Payload) == 0 {
return fmt.Errorf("transaction %d has no payload", i)
}
if len(env.Signature) == 0 {
return fmt.Errorf("transaction %d has no signature", i)
}
expected, err := proto.Marshal(env)
if err != nil {
return fmt.Errorf("failed re-marshaling envelope: %v", err)
}
if len(expected) < len(rawTx) {
return fmt.Errorf("transaction %d has %d trailing bytes", i, len(rawTx)-len(expected))
}
if !bytes.Equal(expected, rawTx) {
return fmt.Errorf("transaction %d (%s) does not match its raw form (%s)", i,
base64.StdEncoding.EncodeToString(expected), base64.StdEncoding.EncodeToString(rawTx))
}
}
return nil
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Check how the block was produced — ensure each Data entry is exactly one proto.Marshal(env) result, never a concatenation.
- Trim or re-serialize: extract the first envelope's bytes and discard the remainder only if you understand the provenance.
- Re-fetch the block from a trusted peer/orderer.
- In block-building tools, always store len(expected) bytes, not len(rawTx).
Example fix
// before: concatenating envelopes
data := append(env1Bytes, env2Bytes...)
// after: one envelope per data entry
block.Data.Data = [][]byte{env1Bytes, env2Bytes} Defensive patterns
Strategy: validation
Validate before calling
expected, err := proto.Marshal(env)
if err != nil { return err }
if len(rawTx) != len(expected) {
return fmt.Errorf("tx %d: length mismatch (%d vs %d), trailing bytes?", i, len(rawTx), len(expected))
} Prevention
- Store exactly one serialized envelope per block Data entry.
- Never concatenate envelope bytes into a single entry.
- Slice buffers to the marshaled length before appending to block data.
- Re-fetch blocks from trusted peers when validation reports trailing bytes.
When it happens
Trigger: BlockDataHash finds len(rawTx) > len(proto.Marshal(env)) at index i, i.e. extra bytes were appended to a serialized envelope inside block.Data.Data.
Common situations: Manual assembly of block data concatenating multiple envelopes into one entry; padding added by a buggy serializer; corrupted storage or a malformed externally generated block; concatenating envelope bytes without splitting in a custom tool.
Related errors
- transaction %d has no payload
- transaction %d has no signature
- transaction %d (%s) does not match its raw form (%s)
- malformed org definition for org: %s
- error encode input
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f00583d30549270c.
Report an issue: GitHub.