{"record":{"id":"745f6d20ac29d457","repo":"hyperledger/fabric","slug":"proto-marshal-called-with-nil-745f6d","errorCode":null,"errorMessage":"proto: Marshal called with nil","messagePattern":"proto: Marshal called with nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gossip/protoext/signing.go","lineNumber":28,"sourceCode":"\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/hyperledger/fabric-protos-go-apiv2/gossip\"\n\t\"google.golang.org/protobuf/proto\"\n)\n\n// Signer signs a message, and returns (signature, nil)\n// on success, and nil and an error on failure.\ntype Signer func(msg []byte) ([]byte, error)\n\n// Verifier receives a peer identity, a signature and a message and returns nil\n// if the signature on the message could be verified using the given identity.\ntype Verifier func(peerIdentity []byte, signature, message []byte) error\n\n// SignSecret signs the secret payload and creates a secret envelope out of it.\nfunc SignSecret(e *gossip.Envelope, signer Signer, secret *gossip.Secret) error {\n\tif secret == nil {\n\t\treturn errors.New(\"proto: Marshal called with nil\")\n\t}\n\tpayload, err := proto.Marshal(secret)\n\tif err != nil {\n\t\treturn err\n\t}\n\tsig, err := signer(payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\te.SecretEnvelope = &gossip.SecretEnvelope{\n\t\tPayload:   payload,\n\t\tSignature: sig,\n\t}\n\treturn nil\n}\n\n// NoopSign creates a SignedGossipMessage with a nil signature\nfunc NoopSign(m *gossip.GossipMessage) (*SignedGossipMessage, error) {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/gossip/protoext/signing.go#L10-L46","documentation":"SignSecret returns this error when the given *gossip.Secret is nil, mirroring the message protobuf's Marshal would emit. It short-circuits before proto.Marshal to avoid a panic/nil error deeper in serialization.","triggerScenarios":"Calling SignSecret(e, signer, nil) — e.g. an envelope that has no SecretEnvelope content to attach, or a caller passing a nil secret extracted from a failed parse.","commonSituations":"Building authenticated gossip envelopes where the secret (e.g. internal endpoint) is absent; refactoring code that changed when secrets are populated; tests passing nil for brevity.","solutions":["Pass a non-nil gossip.Secret to SignSecret, or skip signing entirely when no secret exists","Check the upstream code path that produced the Secret and fix the nil assignment","Guard the call site: only call SignSecret when a secret is required and present"],"exampleFix":"// before\nprotoext.SignSecret(envelope, signer, secret) // secret may be nil\n// after\nif secret != nil {\n    err := protoext.SignSecret(envelope, signer, secret)\n}","handlingStrategy":"type-guard","validationCode":"if secret == nil {\n    return nil // nothing to sign; skip SignSecret\n}","typeGuard":"func hasSecret(s *gossip.Secret) bool { return s != nil }","tryCatchPattern":"if err := protoext.SignSecret(env, signer, secret); err != nil {\n    if err.Error() == \"proto: Marshal called with nil\" {\n        return fmt.Errorf(\"no secret provided to sign: %w\", err)\n    }\n    return err\n}","preventionTips":["Only call SignSecret when the envelope actually carries a secret","Check the Secret extraction/parse step for nil returns","Add a unit test covering the nil-secret call"],"tags":["gossip","hyperledger-fabric","nil-argument","serialization"],"backgroundTag":"proto-marshal-nil","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"}