hyperledger/fabric · error
received proposal response with nil response
Error message
received proposal response with nil response
What it means
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.
Source
Thrown at internal/peer/lifecycle/chaincode/getinstalledpackage.go:139
return errors.WithMessage(err, "failed to create proposal")
}
signedProposal, err := signProposal(proposal, i.Signer)
if err != nil {
return errors.WithMessage(err, "failed to create signed proposal")
}
proposalResponse, err := i.EndorserClient.ProcessProposal(context.Background(), signedProposal)
if err != nil {
return errors.WithMessage(err, "failed to endorse proposal")
}
if proposalResponse == nil {
return errors.New("received nil proposal response")
}
if proposalResponse.Response == nil {
return errors.New("received proposal response with nil response")
}
if proposalResponse.Response.Status != int32(cb.Status_SUCCESS) {
return errors.Errorf("proposal failed with status: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message)
}
return i.writePackage(proposalResponse)
}
func (i *InstalledPackageGetter) writePackage(proposalResponse *pb.ProposalResponse) error {
result := &lb.GetInstalledChaincodePackageResult{}
err := proto.Unmarshal(proposalResponse.Response.Payload, result)
if err != nil {
return errors.Wrap(err, "failed to unmarshal proposal response's response payload")
}
outputFile := filepath.Join(i.Input.OutputDirectory, i.Input.PackageID+".tar.gz")
View on GitHub (pinned to 2736b63f8f)
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
Example fix
// before
return &pb.ProposalResponse{}, nil // Response nil
// after
return &pb.ProposalResponse{Response: &pb.Response{Status: 200, Payload: resultBytes}}, nil Defensive patterns
Strategy: type-guard
Type guard
func hasInnerResponse(pr *pb.ProposalResponse) bool {
return pr != nil && pr.Response != nil
} Try / catch
if resp == nil {
return errors.New("received nil proposal response")
}
if resp.Response == nil {
return errors.New("received proposal response with nil response")
}
if resp.Response.Status != int32(cb.Status_SUCCESS) {
return fmt.Errorf("proposal failed with status: %d - %s", resp.Response.Status, resp.Response.Message)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Partially constructed responses in test mocks; middleware rewriting responses and dropping the inner message.
Related errors
- received nil proposal response
- env cannot be nil if buf and depspec are not nil
- nil data
- nil data bytes
- empty header extension
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/d598a92697eea71c.
Report an issue: GitHub.