{"record":{"id":"47761a7c608a3ad0","repo":"hyperledger/fabric","slug":"received-nil-proposal-response-47761a","errorCode":null,"errorMessage":"received nil proposal response","messagePattern":"received nil proposal response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/peer/lifecycle/chaincode/getinstalledpackage.go","lineNumber":135,"sourceCode":"\t}\n\n\tproposal, err := i.createProposal()\n\tif err != nil {\n\t\treturn errors.WithMessage(err, \"failed to create proposal\")\n\t}\n\n\tsignedProposal, err := signProposal(proposal, i.Signer)\n\tif err != nil {\n\t\treturn errors.WithMessage(err, \"failed to create signed proposal\")\n\t}\n\n\tproposalResponse, err := i.EndorserClient.ProcessProposal(context.Background(), signedProposal)\n\tif err != nil {\n\t\treturn errors.WithMessage(err, \"failed to endorse proposal\")\n\t}\n\n\tif proposalResponse == nil {\n\t\treturn errors.New(\"received nil proposal response\")\n\t}\n\n\tif proposalResponse.Response == nil {\n\t\treturn errors.New(\"received proposal response with nil response\")\n\t}\n\n\tif proposalResponse.Response.Status != int32(cb.Status_SUCCESS) {\n\t\treturn errors.Errorf(\"proposal failed with status: %d - %s\", proposalResponse.Response.Status, proposalResponse.Response.Message)\n\t}\n\n\treturn i.writePackage(proposalResponse)\n}\n\nfunc (i *InstalledPackageGetter) writePackage(proposalResponse *pb.ProposalResponse) error {\n\tresult := &lb.GetInstalledChaincodePackageResult{}\n\terr := proto.Unmarshal(proposalResponse.Response.Payload, result)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to unmarshal proposal response's response payload\")","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/peer/lifecycle/chaincode/getinstalledpackage.go#L117-L153","documentation":"In getinstalledpackage.go Get, after ProcessProposal returns without error, the code defensively checks that the returned *pb.ProposalResponse is non-nil. A nil response despite a nil error indicates a misbehaving endorser client/connection layer. This is a defensive invariant check rather than an expected user-facing failure.","triggerScenarios":"i.EndorserClient.ProcessProposal returns (nil, nil) — abnormal gRPC client behavior, custom/intercepted client implementations, or mocks in tests returning nil responses with nil errors.","commonSituations":"Custom EndorserClient stubs in tests; exotic transports/interceptors dropping the response; virtually never with the stock gRPC endorser client.","solutions":["If in tests, fix the mock to return a valid ProposalResponse","Inspect interceptors/proxies wrapping the endorser client that may swallow responses","Retry the command; if persistent, check peer connectivity and client library version"],"exampleFix":"// before\nmock.On(\"ProcessProposal\").Return(nil, nil)\n// after\nmock.On(\"ProcessProposal\").Return(&pb.ProposalResponse{Response: &pb.Response{Status: 200, Payload: payload}}, nil)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func validProposalResponse(pr *pb.ProposalResponse) bool {\n    return pr != nil\n}","tryCatchPattern":"resp, err := client.ProcessProposal(ctx, sp)\nif err != nil {\n    return errors.WithMessage(err, \"failed to endorse proposal\")\n}\nif resp == nil {\n    return errors.New(\"received nil proposal response\")\n}","preventionTips":["Make test mocks return fully populated ProposalResponse objects","Avoid interceptors that can drop gRPC responses","Never return (nil, nil) from client wrapper implementations"],"tags":["fabric","endorser","nil-check","grpc"],"backgroundTag":"nil-proposal-response","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}