hyperledger/fabric · error

failed re-marshaling envelope: %v

Error message

failed re-marshaling envelope: %v

What it means

During well-formedness verification the Envelope is re-marshaled with proto.Marshal(env) to compare against the original raw bytes. If proto.Marshal returns an error (e.g. an invalid required field or a marshal failure inside the payload submessage), the function surfaces it wrapped as 'failed re-marshaling envelope: %v'. This guards against envelopes that unmarshal but cannot round-trip deterministically.

Source

Thrown at protoutil/blockutils.go:343

	}

	for i, rawTx := range bd.Data {
		env := &cb.Envelope{}
		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. Read the wrapped %v cause to identify which field/submessage failed to marshal.
  2. Rebuild the envelope with the same protobuf library version (google.golang.org/protobuf) used by the rest of the network.
  3. Re-fetch or regenerate the block from a trusted source.
  4. If caused by unknown fields, re-marshal through a clean proto.Clone to canonicalize before hashing.

Example fix

// before: mixing github.com/golang/protobuf and google.golang.org/protobuf
import "github.com/golang/protobuf/proto"
// after
import "google.golang.org/protobuf/proto"
Defensive patterns

Strategy: try-catch

Validate before calling

env := &cb.Envelope{}
if err := proto.Unmarshal(rawTx, env); err != nil { return err }
if _, err := proto.Marshal(env); err != nil {
	return fmt.Errorf("envelope does not round-trip: %w", err)
}

Try / catch

defer func() {
	if r := recover(); r != nil {
		log.Printf("block verification panicked: %v", r)
	}
}()
if err := protoutil.VerifyTransactionsAreWellFormed(block); err != nil {
	return fmt.Errorf("malformed block rejected: %w", err)
}

Prevention

When it happens

Trigger: BlockDataHash iterates block data, successfully unmarshals an Envelope, but proto.Marshal(env) fails — typically due to unknown/invalid fields or a marshal error deep inside Payload/ChannelHeader submessages.

Common situations: Blocks produced by a different protobuf runtime version with incompatible wire data; corrupted submessages that unmarshal leniently but fail strict re-marshal; hand-edited protobuf bytes in test fixtures.

Related errors


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