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

  1. Compare the two base64 strings in the error to identify which fields differ.
  2. Ensure the producer serialized the envelope exactly once with proto.Marshal and stored that output unmodified.
  3. Align protobuf library/runtime versions between block producer and verifier.
  4. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/6198a38158bfe36b. Report an issue: GitHub.