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
- Inspect the panic value's message to find which message/field failed to marshal.
- Regenerate .pb.go files with protoc-gen-go matching your google.golang.org/protobuf version.
- Rebuild the offending message from scratch rather than mutating a partially built one.
- 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
- Recover around MarshalOrPanic at boundaries between panic-based and error-based code.
- Regenerate .pb.go files when upgrading the protobuf runtime.
- Build messages from scratch rather than mutating partially constructed ones.
- Use protoutil.Marshal where a graceful error return is possible.
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
- error marshaling
- unmarshal failed
- marshal failed
- failed re-marshaling envelope: %v
- proto: Marshal called with nil
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/92f38b2e9c20d48f.
Report an issue: GitHub.