hyperledger/fabric · error

no proposal responses received - this might indicate a bug

Error message

no proposal responses received - this might indicate a bug

What it means

After endorsing the proposal, ChaincodeInvokeOrQuery expects at least one ProposalResponse. An empty slice means the endorsing path returned success with no responses, which the code treats as impossible outside of a bug — hence the message.

Source

Thrown at internal/peer/chaincode/common.go:530

	prop, txid, err := protoutil.CreateChaincodeProposalWithTxIDAndTransient(pcommon.HeaderType_ENDORSER_TRANSACTION, cID, invocation, creator, txID, tMap)
	if err != nil {
		return nil, errors.WithMessagef(err, "error creating proposal for %s", funcName)
	}

	signedProp, err := protoutil.GetSignedProposal(prop, signer)
	if err != nil {
		return nil, errors.WithMessagef(err, "error creating signed proposal for %s", funcName)
	}

	responses, err := processProposals(endorserClients, signedProp)
	if err != nil {
		return nil, errors.WithMessagef(err, "error endorsing %s", funcName)
	}

	if len(responses) == 0 {
		// this should only happen if some new code has introduced a bug
		return nil, errors.New("no proposal responses received - this might indicate a bug")
	}
	// all responses will be checked when the signed transaction is created.
	// for now, just set this so we check the first response's status
	proposalResp := responses[0]

	if invoke {
		if proposalResp != nil {
			if proposalResp.Response.Status >= shim.ERRORTHRESHOLD {
				return proposalResp, nil
			}
			// assemble a signed transaction (it's an Envelope message)
			env, err := protoutil.CreateSignedTx(prop, signer, responses...)
			if err != nil {
				return proposalResp, errors.WithMessage(err, "could not assemble transaction")
			}
			var dg *DeliverGroup
			var ctx context.Context
			if waitForEvent {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check for overrides of the endorser client or processProposals in your build/tests and restore defaults
  2. Inspect endorser logs to confirm proposals were actually processed
  3. Upgrade Fabric if reproducible with stock CLI — it indicates an internal bug; report with repro steps

Example fix

// before (stubbed endorser returning empty)
mockEndorser.ProcessProposal = func(...) (*pb.ProposalResponse, error) { return &pb.ProposalResponse{}, nil }
// after
mockEndorser.ProcessProposal = func(...) (*pb.ProposalResponse, error) { return validEndorsementResponse, nil }
Defensive patterns

Strategy: try-catch

Validate before calling

if endorserClient == nil {
    return fmt.Errorf("endorser client must be initialized before invoking")
}

Type guard

func hasResponses(resps []*pb.ProposalResponse) bool { return len(resps) > 0 }

Try / catch

if err != nil && strings.Contains(err.Error(), "no proposal responses received") {
    // treat as internal bug: dump endorser config + override state, escalate
    logger.Errorf("endorser returned zero responses; check GetEndorserClientFnc/processProposals overrides")
}

Prevention

When it happens

Trigger: processProposals/endorser call returns (nil error, empty responses) — typically when the endorser client stub or hook was overridden and returns an empty reply, or new endorser-handling code silently drops all responses.

Common situations: Test harnesses stubbing GetEndorserClientFnc/processProposals; custom middleware wrapping the endorser that filters responses; Fabric regressions after upgrades.

Related errors


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