{"record":{"id":"2b3670874b03d60d","repo":"hyperledger/fabric","slug":"proposal-failed-with-status-d-s","errorCode":null,"errorMessage":"proposal failed with status: %d - %s","messagePattern":"proposal failed with status: (.+?) - (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/peer/lifecycle/chaincode/approveformyorg.go","lineNumber":202,"sourceCode":"\tif len(responses) == 0 {\n\t\t// this should only be empty due to a programming bug\n\t\treturn errors.New(\"no proposal responses received\")\n\t}\n\n\t// all responses will be checked when the signed transaction is created.\n\t// for now, just set this so we check the first response's status\n\tproposalResponse := responses[0]\n\n\tif proposalResponse == nil {\n\t\treturn errors.New(\"received nil proposal response\")\n\t}\n\n\tif proposalResponse.Response == nil {\n\t\treturn errors.Errorf(\"received proposal response with nil response\")\n\t}\n\n\tif proposalResponse.Response.Status != int32(cb.Status_SUCCESS) {\n\t\treturn errors.Errorf(\"proposal failed with status: %d - %s\", proposalResponse.Response.Status, proposalResponse.Response.Message)\n\t}\n\t// assemble a signed transaction (it's an Envelope message)\n\tenv, err := protoutil.CreateSignedTx(proposal, a.Signer, responses...)\n\tif err != nil {\n\t\treturn errors.WithMessage(err, \"failed to create signed transaction\")\n\t}\n\tvar dg *chaincode.DeliverGroup\n\tvar ctx context.Context\n\tif a.Input.WaitForEvent {\n\t\tvar cancelFunc context.CancelFunc\n\t\tctx, cancelFunc = context.WithTimeout(context.Background(), a.Input.WaitForEventTimeout)\n\t\tdefer cancelFunc()\n\n\t\tdg = chaincode.NewDeliverGroup(\n\t\t\ta.DeliverClients,\n\t\t\ta.Input.PeerAddresses,\n\t\t\ta.Signer,\n\t\t\ta.Certificate,","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/peer/lifecycle/chaincode/approveformyorg.go#L184-L220","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: approving with stale sequence and wrong package id\napproveformyorg --channelID mychannel --name mycc --version 1.0 --sequence 1 --package-id cc_1:abc\n// after: query installed, use current package id, bump sequence to next expected\npeer lifecycle chaincode queryinstalled\napproveformyorg --channelID mychannel --name mycc --version 1.0 --sequence 2 --package-id mycc_1:<correct-hash>","handlingStrategy":"validation","validationCode":"// before approving, verify package is installed and sequence is next\nout, _ := exec.Command(\"peer\", \"lifecycle\", \"chaincode\", \"queryinstalled\").Output()\nif !strings.Contains(string(out), expectedPackageID) {\n    return errors.New(\"package not installed on peer; approve will fail\")\n}\n// also compare sequence against queryapproved / committed state\nreadiness, _ := exec.Command(\"peer\", \"lifecycle\", \"chaincode\", \"checkcommitreadiness\",\n    \"--channelID\", ch, \"--name\", cc, \"--version\", v, \"--sequence\", seq, \"--output\", \"json\").Output()\n_ = readiness","typeGuard":null,"tryCatchPattern":"resp, err := approver.Approve(proposal)\nif err != nil {\n    var statusErr interface{ Status() int32 }\n    // inspect proposalResponse.Response.Status/Message to branch on\n    // 410/ALREADY_APPROVED-style messages vs hard failures\n    return fmt.Errorf(\"approve rejected: %w\", err)\n}","preventionTips":["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."],"tags":["fabric","chaincode-lifecycle","endorsement","approval"],"backgroundTag":"proposal-endorsement-rejected","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}