hyperledger/fabric · error

received proposal response with nil response

Error message

received proposal response with nil response

What it means

CommittedQuerier.Query validates the ProposalResponse returned by the peer's endorser before printing results. This error means the endorser returned a non-nil ProposalResponse whose nested Response field is nil, so the query result cannot be inspected. It is thrown as a defensive sanity check because a well-formed endorsement always carries a Response with status and payload.

Source

Thrown at internal/peer/lifecycle/chaincode/querycommitted.go:133

		return errors.WithMessage(err, "failed to create proposal")
	}

	signedProposal, err := signProposal(proposal, c.Signer)
	if err != nil {
		return errors.WithMessage(err, "failed to create signed proposal")
	}

	proposalResponse, err := c.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("query failed with status: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message)
	}

	if strings.ToLower(c.Input.OutputFormat) == "json" {
		return c.printResponseAsJSON(proposalResponse)
	}
	return c.printResponse(proposalResponse)
}

func (c *CommittedQuerier) printResponseAsJSON(proposalResponse *pb.ProposalResponse) error {
	if c.Input.Name != "" {
		return printResponseAsJSON(proposalResponse, &lb.QueryChaincodeDefinitionResult{}, c.Writer)
	}
	return printResponseAsJSON(proposalResponse, &lb.QueryChaincodeDefinitionsResult{}, c.Writer)
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify peer and CLI Fabric versions match and the peer is a genuine Hyperledger Fabric endorser
  2. Retry the query; transient gRPC/proxy corruption may produce a malformed response
  3. Bypass proxies/load balancers and query the peer directly
  4. Check peer logs for endorsement errors around the request time
Defensive patterns

Strategy: type-guard

Validate before calling

// before calling Query / after obtaining a ProposalResponse
func validProposalResponse(pr *pb.ProposalResponse) bool {
    return pr != nil && pr.Response != nil
}

Type guard

func hasResponse(pr *pb.ProposalResponse) bool {
    return pr != nil && pr.Response != nil
}

if !hasResponse(resp) {
    return fmt.Errorf("endorser returned malformed proposal response")
}

Try / catch

if err := q.Query(); err != nil {
    if strings.Contains(err.Error(), "nil response") {
        // malformed endorsement: retry or re-verify peer
        return retryQuery()
    }
    return err
}

Prevention

When it happens

Trigger: Calling 'peer lifecycle chaincode querycommitted' against a peer whose endorser returns a malformed/empty ProposalResponse (nil Response) after ProcessProposal succeeds.

Common situations: Buggy or non-standard peer implementation, proxy/middleware stripping response fields, corrupted gRPC message, or a peer version mismatch producing an incomplete endorsement.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/25f2eca26a8f6020. Report an issue: GitHub.