hyperledger/fabric · error
transaction %d (%s) does not match its raw form (%s)
Error message
transaction %d (%s) does not match its raw form (%s)
What it means
The final well-formedness check requires the re-marshaled Envelope to be byte-identical to the original raw entry. Any difference (same length, different bytes) means the entry is not a canonical serialization of the envelope it claims to be, so block hashing would be ambiguous. The error includes base64 of both forms to aid diagnosis.
Source
Thrown at protoutil/blockutils.go:350
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
- Compare the two base64 strings in the error to identify which fields differ.
- Ensure the producer serialized the envelope exactly once with proto.Marshal and stored that output unmodified.
- Align protobuf library/runtime versions between block producer and verifier.
- Replace the block with a canonical re-marshal from a trusted source if provenance allows.
Example fix
// before: editing raw bytes then storing them
raw[10] = 0x00
block.Data.Data = [][]byte{raw}
// after: modify the message, then re-marshal
env.Payload = newPayload
raw, err := protoutil.Marshal(env) Defensive patterns
Strategy: validation
Validate before calling
expected, err := proto.Marshal(env)
if err != nil { return err }
if !bytes.Equal(expected, rawTx) {
return fmt.Errorf("tx %d: non-canonical serialization", i)
} Prevention
- Treat marshaled envelope bytes as immutable — modify the message, then re-marshal.
- Keep protobuf runtime versions aligned between producers and verifiers.
- Add round-trip equality tests (Marshal/Unmarshal/Marshal) to CI.
- Verify block integrity (hashes) before processing data entries.
When it happens
Trigger: BlockDataHash finds bytes.Equal(expected, rawTx) == false at index i — the raw bytes were modified after marshaling (field reordering, altered unknown fields, in-place edits), even though they still unmarshal successfully.
Common situations: A peer or tool mutated envelope bytes (e.g. re-encoded with a different protobuf runtime producing different field order for the same message); deliberate tampering; copying blocks between fabric versions with changed proto definitions; naive byte-level edits of stored blocks.
Related errors
- transaction %d has no payload
- transaction %d has no signature
- transaction %d has %d trailing bytes
- malformed org definition for org: %s
- error encode input
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/6198a38158bfe36b.
Report an issue: GitHub.