{"record":{"id":"9eeccfb6a4705984","repo":"hyperledger/fabric","slug":"collections-do-not-match","errorCode":null,"errorMessage":"Collections do not match","messagePattern":"Collections do not match","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/lifecycle.go","lineNumber":136,"sourceCode":"\tEndorsementInfo *lb.ChaincodeEndorsementInfo\n\tValidationInfo  *lb.ChaincodeValidationInfo\n\tCollections     *pb.CollectionConfigPackage\n}\n\nfunc (cp *ChaincodeParameters) Equal(ocp *ChaincodeParameters) error {\n\tswitch {\n\tcase cp.EndorsementInfo.Version != ocp.EndorsementInfo.Version:\n\t\treturn errors.Errorf(\"expected Version '%s' does not match passed Version '%s'\", cp.EndorsementInfo.Version, ocp.EndorsementInfo.Version)\n\tcase cp.EndorsementInfo.EndorsementPlugin != ocp.EndorsementInfo.EndorsementPlugin:\n\t\treturn errors.Errorf(\"expected EndorsementPlugin '%s' does not match passed EndorsementPlugin '%s'\", cp.EndorsementInfo.EndorsementPlugin, ocp.EndorsementInfo.EndorsementPlugin)\n\tcase cp.EndorsementInfo.InitRequired != ocp.EndorsementInfo.InitRequired:\n\t\treturn errors.Errorf(\"expected InitRequired '%t' does not match passed InitRequired '%t'\", cp.EndorsementInfo.InitRequired, ocp.EndorsementInfo.InitRequired)\n\tcase cp.ValidationInfo.ValidationPlugin != ocp.ValidationInfo.ValidationPlugin:\n\t\treturn errors.Errorf(\"expected ValidationPlugin '%s' does not match passed ValidationPlugin '%s'\", cp.ValidationInfo.ValidationPlugin, ocp.ValidationInfo.ValidationPlugin)\n\tcase !bytes.Equal(cp.ValidationInfo.ValidationParameter, ocp.ValidationInfo.ValidationParameter):\n\t\treturn errors.Errorf(\"expected ValidationParameter '%x' does not match passed ValidationParameter '%x'\", cp.ValidationInfo.ValidationParameter, ocp.ValidationInfo.ValidationParameter)\n\tcase !proto.Equal(cp.Collections, ocp.Collections):\n\t\treturn errors.Errorf(\"Collections do not match\")\n\tdefault:\n\t}\n\treturn nil\n}\n\n// ChaincodeDefinition contains the chaincode parameters, as well as the sequence number of the definition.\n// Note, it does not embed ChaincodeParameters so as not to complicate the serialization.  It is expected\n// that any instance will have no nil fields once initialized.\n// WARNING: This structure is serialized/deserialized from the DB, re-ordering or adding fields\n// will cause opaque checks to fail.\ntype ChaincodeDefinition struct {\n\tSequence        int64\n\tEndorsementInfo *lb.ChaincodeEndorsementInfo\n\tValidationInfo  *lb.ChaincodeValidationInfo\n\tCollections     *pb.CollectionConfigPackage\n}\n\ntype ApprovedChaincodeDefinition struct {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/lifecycle.go#L118-L154","documentation":"Thrown by ChaincodeParameters.Equal when the Collections package (private data collection configuration) of the new definition is not proto.Equal to the committed one. Collection configuration is part of the chaincode definition and cannot change without a new sequence.","triggerScenarios":"Committing a definition whose CollectionConfigPackage differs (added/removed/modified collections) from the committed definition at the same sequence number.","commonSituations":"Updating collections.json (adding a private data collection) without incrementing sequence; inconsistent collections config approved by different orgs; field-order/name typos making the proto differ.","solutions":["Keep collections identical to the committed definition, or increment the sequence number when intentionally updating collections","Re-approve with the same collections.json on all organizations","Validate the collections JSON before approval (peer lifecycle chaincode approveformyorg --collections-file)"],"exampleFix":"// before\ncollections: {newCollection added}, sequence: 1 // committed had original collections\n// after\noriginal collections, sequence: 1 // or sequence: 2 with the new collection","handlingStrategy":"validation","validationCode":"committed, err := lifecycle.QueryChaincodeDefinition(chname, ccname, publicState)\nif err == nil && !proto.Equal(newDef.Collections, committed.Collections) && newDef.Sequence == committed.Sequence {\n    return fmt.Errorf(\"collections change requires sequence bump\")\n}","typeGuard":"func sameCollections(a, b *lifecycle.ChaincodeParameters) bool {\n    return a != nil && b != nil && proto.Equal(a.Collections, b.Collections)\n}","tryCatchPattern":"if err := params.Equal(committedParams); err != nil {\n    if strings.Contains(err.Error(), \"Collections do not match\") {\n        // reuse committed collections config or bump sequence\n    }\n    return err\n}","preventionTips":["Validate collections.json with the peer before every approval","Distribute the exact same collections file to all organizations' approval commands","Bump the sequence whenever adding/modifying private data collections"],"tags":["hyperledger-fabric","lifecycle","private-data","collections-mismatch"],"backgroundTag":"chaincode-definition-mismatch","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"}