{"record":{"id":"d598a92697eea71c","repo":"hyperledger/fabric","slug":"received-proposal-response-with-nil-response-d598a9","errorCode":null,"errorMessage":"received proposal response with nil response","messagePattern":"received proposal response with nil response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/peer/lifecycle/chaincode/getinstalledpackage.go","lineNumber":139,"sourceCode":"\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\")\n\t}\n\n\toutputFile := filepath.Join(i.Input.OutputDirectory, i.Input.PackageID+\".tar.gz\")\n","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/peer/lifecycle/chaincode/getinstalledpackage.go#L121-L157","documentation":"After confirming the ProposalResponse itself is non-nil, Get verifies the embedded Response message is also non-nil before reading Status/Payload. A nil Response means the endorser returned a structurally incomplete reply. Like the nil proposal response check, this is defensive validation of endorser output.","triggerScenarios":"ProcessProposal returns a ProposalResponse with a nil Response field — again only via custom clients, interceptors, or test mocks that populate the outer struct but not Response.","commonSituations":"Partially constructed responses in test mocks; middleware rewriting responses and dropping the inner message.","solutions":["Fix the producing endorser/client/mock to include a pb.Response with Status and Payload","Add a guard before consuming the response if writing custom client code","Use the stock fabric endorser client path where this cannot occur"],"exampleFix":"// before\nreturn &pb.ProposalResponse{}, nil // Response nil\n// after\nreturn &pb.ProposalResponse{Response: &pb.Response{Status: 200, Payload: resultBytes}}, nil","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func hasInnerResponse(pr *pb.ProposalResponse) bool {\n    return pr != nil && pr.Response != nil\n}","tryCatchPattern":"if resp == nil {\n    return errors.New(\"received nil proposal response\")\n}\nif resp.Response == nil {\n    return errors.New(\"received proposal response with nil response\")\n}\nif resp.Response.Status != int32(cb.Status_SUCCESS) {\n    return fmt.Errorf(\"proposal failed with status: %d - %s\", resp.Response.Status, resp.Response.Message)\n}","preventionTips":["Always populate the inner pb.Response in custom endorsers/mocks","Check Status == 200 (SUCCESS) before reading Payload","Centralize response validation in one helper reused by all client wrappers"],"tags":["fabric","endorser","nil-check"],"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-08T10:18:20.063Z"}