hyperledger/fabric · error

proposal response was not successful, error code %d, msg %s

Error message

proposal response was not successful, error code %d, msg %s

What it means

CreateSignedTx validates that every proposal response has a successful status code (200-399). If any response reports an error status, the transaction cannot proceed and the error includes the peer's status code and message, which come from chaincode execution or endorser rejection.

Source

Thrown at protoutil/txutils.go:182

	signerBytes, err := signer.Serialize()
	if err != nil {
		return nil, err
	}

	shdr, err := UnmarshalSignatureHeader(hdr.SignatureHeader)
	if err != nil {
		return nil, err
	}

	if !bytes.Equal(signerBytes, shdr.Creator) {
		return nil, errors.New("signer must be the same as the one referenced in the header")
	}

	// ensure that all actions are bitwise equal and that they are successful
	var a1 []byte
	for n, r := range resps {
		if r.Response.Status < 200 || r.Response.Status >= 400 {
			return nil, errors.Errorf("proposal response was not successful, error code %d, msg %s", r.Response.Status, r.Response.Message)
		}

		if n == 0 {
			a1 = r.Payload
			continue
		}

		if !bytes.Equal(a1, r.Payload) {
			return nil, errors.Errorf("ProposalResponsePayloads do not match (base64): '%s' vs '%s'",
				b64.StdEncoding.EncodeToString(r.Payload), b64.StdEncoding.EncodeToString(a1))
		}
	}

	// fill endorsements according to their uniqueness
	endorsersUsed := make(map[string]struct{})
	var endorsements []*peer.Endorsement
	for _, r := range resps {
		if r.Endorsement == nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Inspect r.Response.Status and r.Response.Message to find the chaincode/endorsement failure cause
  2. Fix the chaincode logic or the invoke arguments that caused the failure status
  3. For MVCC conflicts, retry the transaction or reduce key contention
  4. Ensure all collected responses are successful and consistent before calling CreateSignedTx

Example fix

// before
env, err := protoutil.CreateSignedTx(proposal, signer, resps...) // one resp has status 500
// after
for _, r := range resps {
    if r.Response.Status < 200 || r.Response.Status >= 400 {
        return nil, fmt.Errorf("endorsement failed (%d): %s", r.Response.Status, r.Response.Message)
    }
}
env, err := protoutil.CreateSignedTx(proposal, signer, resps...)
Defensive patterns

Strategy: validation

Validate before calling

func allResponsesSuccessful(resps []*peer.ProposalResponse) error {
    for _, r := range resps {
        if r.Response.Status < 200 || r.Response.Status >= 400 {
            return fmt.Errorf("endorsement %d: %s", r.Response.Status, r.Response.Message)
        }
    }
    return nil
}

Type guard

func isSuccess(r *peer.ProposalResponse) bool {
    return r != nil && r.Response != nil && r.Response.Status >= 200 && r.Response.Status < 400
}

Try / catch

if err := allResponsesSuccessful(resps); err != nil {
    // inspect status/message, retry invoke or surface chaincode error
    return nil, err
}
tx, err := protoutil.CreateSignedTx(proposal, signer, resps...)

Prevention

When it happens

Trigger: A chaincode invocation returned an error status (e.g. 500 with 'transaction returned with failure') or an endorser rejected the proposal (e.g. 400 for MVCC conflict, endorsement policy failure), and the caller still tries to assemble a transaction.

Common situations: Chaincode returned an error from Invoke; read-write set conflicts (MVCC_READ_CONFLICT) under concurrency; endorsement policy violations; chaincode container errors/timeout.

Related errors


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