hyperledger/fabric · critical

err

Error message

err

What it means

MarshalOrPanic panics with the raw error when proto.Marshal fails after the nil check. Since valid messages rarely fail to marshal, this panic indicates a genuine serialization problem (unsupported field, internal protobuf error). The panic value is the error itself, so the message string equals the underlying proto.Marshal error ('err').

Source

Thrown at protoutil/commonutils.go:28

	"crypto/rand"
	"fmt"

	cb "github.com/hyperledger/fabric-protos-go-apiv2/common"
	"github.com/hyperledger/fabric/internal/pkg/identity"
	"github.com/pkg/errors"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/timestamppb"
)

// MarshalOrPanic serializes a protobuf message and panics if this
// operation fails
func MarshalOrPanic(pb proto.Message) []byte {
	if !pb.ProtoReflect().IsValid() {
		panic(errors.New("proto: Marshal called with nil"))
	}
	data, err := proto.Marshal(pb)
	if err != nil {
		panic(err)
	}
	return data
}

// Marshal serializes a protobuf message.
func Marshal(pb proto.Message) ([]byte, error) {
	if !pb.ProtoReflect().IsValid() {
		return nil, errors.New("proto: Marshal called with nil")
	}
	return proto.Marshal(pb)
}

// CreateNonceOrPanic generates a nonce using the common/crypto package
// and panics if this operation fails.
func CreateNonceOrPanic() []byte {
	nonce, err := CreateNonce()
	if err != nil {
		panic(err)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Inspect the panic value's message to find which message/field failed to marshal.
  2. Regenerate .pb.go files with protoc-gen-go matching your google.golang.org/protobuf version.
  3. Rebuild the offending message from scratch rather than mutating a partially built one.
  4. Replace MarshalOrPanic with protoutil.Marshal where a graceful error path is preferable.

Example fix

// before
raw := protoutil.MarshalOrPanic(msg)
// after
raw, err := protoutil.Marshal(msg)
if err != nil {
	return fmt.Errorf("marshal failed: %w", err)
}
Defensive patterns

Strategy: try-catch

Try / catch

func marshalSafe(pb proto.Message) (data []byte, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("MarshalOrPanic failed: %v", r)
		}
	}()
	data = protoutil.MarshalOrPanic(pb)
	return
}

Prevention

When it happens

Trigger: Calling MarshalOrPanic on a message whose proto.Marshal returns an error — e.g. a message built with corrupt nested state, or an extension/unknown-field problem in the protobuf runtime.

Common situations: Block or config generation (doOutputBlock, doOutputChannelCreateTx) with malformed nested messages; version mismatch between generated .pb.go code and the protobuf runtime; memory corruption in long-running processes.

Related errors


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