{"record":{"id":"9bd8ccf8ef767e80","repo":"hyperledger/fabric","slug":"proto-marshal-called-with-nil-9bd8cc","errorCode":null,"errorMessage":"proto: Marshal called with nil","messagePattern":"proto: Marshal called with nil","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"protoutil/commonutils.go","lineNumber":24,"sourceCode":"\npackage protoutil\n\nimport (\n\t\"crypto/rand\"\n\t\"fmt\"\n\n\tcb \"github.com/hyperledger/fabric-protos-go-apiv2/common\"\n\t\"github.com/hyperledger/fabric/internal/pkg/identity\"\n\t\"github.com/pkg/errors\"\n\t\"google.golang.org/protobuf/proto\"\n\t\"google.golang.org/protobuf/types/known/timestamppb\"\n)\n\n// MarshalOrPanic serializes a protobuf message and panics if this\n// operation fails\nfunc MarshalOrPanic(pb proto.Message) []byte {\n\tif !pb.ProtoReflect().IsValid() {\n\t\tpanic(errors.New(\"proto: Marshal called with nil\"))\n\t}\n\tdata, err := proto.Marshal(pb)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn data\n}\n\n// Marshal serializes a protobuf message.\nfunc Marshal(pb proto.Message) ([]byte, error) {\n\tif !pb.ProtoReflect().IsValid() {\n\t\treturn nil, errors.New(\"proto: Marshal called with nil\")\n\t}\n\treturn proto.Marshal(pb)\n}\n\n// CreateNonceOrPanic generates a nonce using the common/crypto package\n// and panics if this operation fails.","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/commonutils.go#L6-L42","documentation":"MarshalOrPanic serializes a protobuf message and panics on failure. Before marshaling it checks pb.ProtoReflect().IsValid(); a message holding a nil concrete pointer (typed nil) is invalid, and calling proto.Marshal on it panics inside the protobuf runtime. The library converts that into an explicit panic with the message 'proto: Marshal called with nil' so the failure is attributable to this helper.","triggerScenarios":"Calling MarshalOrPanic with a typed-nil message, e.g. protoutil.MarshalOrPanic((*cb.Envelope)(nil)) or a function that returned a nil *Envelope with a non-nil error ignored by the caller.","commonSituations":"serializeIdentity or block-building helpers receiving results of failed constructors whose errors were ignored; zero-value struct pointers in config-generation code; refactors where a factory started returning nil on an error path.","solutions":["Check the variable passed to MarshalOrPanic for nil before the call: if pb == nil { ... }.","Audit the function that produced the message — handle its error return instead of ignoring it.","Switch to protoutil.Marshal (non-panicking) at call sites where nil is plausible.","Add a guard/helper that logs and returns an error instead of panicking in production paths."],"exampleFix":"// before\nraw := protoutil.MarshalOrPanic(env) // env may be nil\n// after\nif env == nil {\n\treturn errors.New(\"envelope is nil\")\n}\nraw, err := protoutil.Marshal(env)\nif err != nil { return err }","handlingStrategy":"type-guard","validationCode":"if env == nil {\n\treturn errors.New(\"cannot marshal nil envelope\")\n}\nraw := protoutil.MarshalOrPanic(env)","typeGuard":"func isValidMessage(pb proto.Message) bool {\n\treturn pb != nil && pb.ProtoReflect().IsValid()\n}","tryCatchPattern":"func safeMarshal(pb proto.Message) (raw []byte, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"marshal panicked: %v\", r)\n\t\t}\n\t}()\n\traw = protoutil.MarshalOrPanic(pb)\n\treturn\n}","preventionTips":["Never pass typed-nil pointers to MarshalOrPanic.","Always check errors from constructors before marshaling their result.","Prefer protoutil.Marshal in code paths where nil is plausible.","Keep panics out of production request paths; reserve OrPanic helpers for init/genesis code."],"tags":["hyperledger-fabric","protobuf","panic","nil-pointer"],"backgroundTag":"nil-message-marshal-panic","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}