hyperledger/fabric · error
proposal failed with status: %d - %s
Error message
proposal failed with status: %d - %s
What it means
This error is thrown in ApproverForMyOrg.Approve when the peer's endorsement of the _lifecycle ApproveChaincodeDefinitionForMyOrg proposal returned a non-SUCCESS status. It means the peer rejected the chaincode definition approval; the gRPC Status and Message from the proposal response are embedded to explain why. Common causes are lifecycle precheck failures, a mismatched sequence number, or the chaincode package not being installed on that peer.
Source
Thrown at internal/peer/lifecycle/chaincode/approveformyorg.go:202
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.Errorf("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, a.Signer, responses...)
if err != nil {
return errors.WithMessage(err, "failed to create signed transaction")
}
var dg *chaincode.DeliverGroup
var ctx context.Context
if a.Input.WaitForEvent {
var cancelFunc context.CancelFunc
ctx, cancelFunc = context.WithTimeout(context.Background(), a.Input.WaitForEventTimeout)
defer cancelFunc()
dg = chaincode.NewDeliverGroup(
a.DeliverClients,
a.Input.PeerAddresses,
a.Signer,
a.Certificate,View on GitHub (pinned to 2736b63f8f)
Solutions
- Check the Message in the error output — it carries the peer's rejection reason (e.g. 'chaincode with name X and version Y already approved with sequence Z').
- Verify the chaincode package is installed on the peer: `peer lifecycle chaincode queryinstalled` and confirm the packageID matches --package-id.
- Run `peer lifecycle chaincode queryapproved` / check `checkcommitreadiness` to confirm the correct sequence number; increment sequence if the definition already exists.
- If the definition was already approved with identical fields, no action needed — proceed to checkcommitreadiness/commit instead of re-approving.
- Fix any initRequired or collection config mismatches versus the committed definition and rerun with -C/--channelID and correct flags.
Example fix
// before: approving with stale sequence and wrong package id approveformyorg --channelID mychannel --name mycc --version 1.0 --sequence 1 --package-id cc_1:abc // after: query installed, use current package id, bump sequence to next expected peer lifecycle chaincode queryinstalled approveformyorg --channelID mychannel --name mycc --version 1.0 --sequence 2 --package-id mycc_1:<correct-hash>
Defensive patterns
Strategy: validation
Validate before calling
// before approving, verify package is installed and sequence is next
out, _ := exec.Command("peer", "lifecycle", "chaincode", "queryinstalled").Output()
if !strings.Contains(string(out), expectedPackageID) {
return errors.New("package not installed on peer; approve will fail")
}
// also compare sequence against queryapproved / committed state
readiness, _ := exec.Command("peer", "lifecycle", "chaincode", "checkcommitreadiness",
"--channelID", ch, "--name", cc, "--version", v, "--sequence", seq, "--output", "json").Output()
_ = readiness Try / catch
resp, err := approver.Approve(proposal)
if err != nil {
var statusErr interface{ Status() int32 }
// inspect proposalResponse.Response.Status/Message to branch on
// 410/ALREADY_APPROVED-style messages vs hard failures
return fmt.Errorf("approve rejected: %w", err)
} Prevention
- Always run queryinstalled and confirm the packageID before approving.
- Derive the sequence from current committed definitions; never hardcode sequence 1 for upgrades.
- Use checkcommitreadiness to confirm org approval state before/after approve.
- Keep packageIDs stable by repackaging only when chaincode source changes.
When it happens
Trigger: Running `peer lifecycle chaincode approveformyorg` where the proposal response from the peer has Response.Status != 200. Specific causes include: packageID not installed on the peer, sequence number lower than the current defined sequence, initRequired mismatch with the previous definition, collection/configuration changes failing validation, or the peer not having the org's endorsement of prerequisites.
Common situations: Approving a definition whose sequence was already approved (stale sequence), approving before `peer lifecycle chaincode install` on the peer so the packageID is unknown, a typo'd packageID after re-packaging, or endorsement policy/collection changes rejected by the peer's definition validation.
Related errors
- implicit policy evaluation failed - %d sub-policies were sat
- chaincode definition for '%s' at sequence %d on channel '%s'
- chaincode definition for '%s' exists, but chaincode is not i
- could not get channel config for channel '%s'
- chaincode definition not agreed to by this org (%s)
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/2b3670874b03d60d.
Report an issue: GitHub.