{"record":{"id":"083b5802c5a907a2","repo":"hyperledger/fabric","slug":"attempted-to-redefine-uncommitted-sequence-d-fo","errorCode":null,"errorMessage":"attempted to redefine uncommitted sequence (%d) for namespace %s with unchanged content","messagePattern":"attempted to redefine uncommitted sequence \\((.+?)\\) for namespace (.+?) with unchanged content","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/chaincode/lifecycle/lifecycle.go","lineNumber":487,"sourceCode":"\t\tredefine, err := ef.isAttemptToRedefine(privateName, packageID, requestedSequence, cd, orgState)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif redefine {\n\t\t\treturn errors.Errorf(\"attempted to redefine the current committed sequence (%d) for namespace %s\", currentSequence, ccname)\n\t\t}\n\t}\n\n\t// if requested sequence is not committed, and attempt is made to update its content,\n\t// we need to check whether new definition actually contains updated content, to avoid\n\t// empty write set.\n\tif requestedSequence == currentSequence+1 {\n\t\tredefine, err := ef.isAttemptToRedefine(privateName, packageID, requestedSequence, cd, orgState)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif redefine {\n\t\t\treturn errors.Errorf(\"attempted to redefine uncommitted sequence (%d) for namespace %s with unchanged content\", requestedSequence, ccname)\n\t\t}\n\t}\n\n\tif err := ef.Resources.Serializer.Serialize(NamespacesName, privateName, cd.Parameters(), orgState); err != nil {\n\t\treturn errors.WithMessage(err, \"could not serialize chaincode parameters to state\")\n\t}\n\n\t// set the package id - whether empty or not. Setting\n\t// an empty package ID means that the chaincode won't\n\t// be invocable. The package might be set empty after\n\t// the definition commits as a way of instructing the\n\t// peers of an org no longer to endorse invocations\n\t// for this chaincode\n\tif err := ef.Resources.Serializer.Serialize(ChaincodeSourcesName, privateName, &ChaincodeLocalPackage{\n\t\tPackageID: packageID,\n\t}, orgState); err != nil {\n\t\treturn errors.WithMessage(err, \"could not serialize chaincode package info to state\")\n\t}","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/lifecycle.go#L469-L505","documentation":"The org is approving the next sequence (current+1) which is not yet committed, but the proposed content is byte-for-byte identical to the org's existing uncommitted approval (or committed definition). Lifecycle rejects a no-op write to avoid an empty transaction.","triggerScenarios":"Approving sequence N+1 with the exact same package ID and parameters as the already-approved definition at that org state — e.g., re-approving after a failed commit without changing anything, or re-running the same approve command twice.","commonSituations":"Retry loops that re-approve without changes; intending to change the chaincode but the package ID/parameters stayed identical; forgetting to bump sequence only when content changes.","solutions":["If a real upgrade is intended, change the definition (new package ID via packaged chaincode, updated initialization parameters, or endorsement policy)","If no change is intended, do not re-approve; proceed directly to the commit step","Adjust retry logic to detect an existing matching approval and skip re-approval"],"exampleFix":"// before\npeer lifecycle chaincode approveformyorg -C mychannel --sequence 2 --package-id same:pkgid  # unchanged\n// after\npeer lifecycle chaincode approveformyorg -C mychannel --sequence 2 --package-id <new-hash-of-updated-package>","handlingStrategy":"validation","validationCode":"// Before approving seq N+1, confirm the content actually differs\nprev := orgApprovedDefinition(ch, ccname, seq)\nif prev != nil && prev.PackageID == def.PackageID && paramsEqual(prev, def) {\n    return nil // unchanged; skip approval\n}","typeGuard":null,"tryCatchPattern":"err := ef.ApproveChaincodeDefinitionForOrg(...)\nif err != nil && strings.Contains(err.Error(), \"unchanged content\") {\n    // either proceed to commit (no change intended) or change package/params and retry\n}","preventionTips":["Only bump the sequence together with an actual content change","Hash the definition (package ID + params + policy) and compare before approving","Fix retry loops to skip approve steps when nothing changed"],"tags":["fabric","lifecycle","idempotency"],"backgroundTag":"duplicate-approval","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"}