hyperledger/fabric · error

received proposal response with nil response

Error message

received proposal response with nil response

What it means

Even when the ProposalResponse wrapper is non-nil, its embedded Response payload must be present for Commit to inspect the status. A nil Response is treated as a malformed endorser reply and rejected.

Source

Thrown at internal/peer/lifecycle/chaincode/commit.go:196

		}
		responses = append(responses, proposalResponse)
	}

	if len(responses) == 0 {
		// this should only be empty due to a programming bug
		return errors.New("no proposal responses received")
	}

	// all responses will be checked when the signed transaction is created.
	// for now, just set this so we check the first response's status
	proposalResponse := responses[0]

	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)
	}
	// assemble a signed transaction (it's an Envelope message)
	env, err := protoutil.CreateSignedTx(proposal, c.Signer, responses...)
	if err != nil {
		return errors.WithMessage(err, "failed to create signed transaction")
	}

	var dg *chaincode.DeliverGroup
	var ctx context.Context
	if c.Input.WaitForEvent {
		var cancelFunc context.CancelFunc
		ctx, cancelFunc = context.WithTimeout(context.Background(), c.Input.WaitForEventTimeout)
		defer cancelFunc()

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check the endorser's returned ProposalResponse for a non-nil Response field before appending.
  2. Verify protobuf serialization/deserialization of responses in custom clients.
  3. Use the fabric protoutil helpers to construct responses correctly.
  4. Re-run the transaction against healthy endorsers.

Example fix

// before
responses = append(responses, resp)
// after
if resp == nil || resp.Response == nil { return errors.New("malformed proposal response") }
responses = append(responses, resp)
Defensive patterns

Strategy: type-guard

Validate before calling

for _, resp := range responses {
    if resp == nil || resp.Response == nil {
        return errors.New("malformed proposal response: nil Response")
    }
}

Type guard

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

Try / catch

if err := commit(...); err != nil {
    if strings.Contains(err.Error(), "nil response") {
        // re-endorse; inspect protobuf deserialization in custom clients
    }
}

Prevention

When it happens

Trigger: responses[0].Response is nil when Commit examines the first proposal response — a structurally malformed response from an endorser.

Common situations: Corrupted or hand-crafted proposal responses in custom tooling; proto deserialization producing a non-nil wrapper with nil payload; buggy mock endorsers in tests.

Related errors


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