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

  1. Check how the block was produced — ensure each Data entry is exactly one proto.Marshal(env) result, never a concatenation.
  2. Trim or re-serialize: extract the first envelope's bytes and discard the remainder only if you understand the provenance.
  3. Re-fetch the block from a trusted peer/orderer.
  4. 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

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


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