{"record":{"id":"e48b8537defaaf04","repo":"hyperledger/fabric","slug":"existing-collection-s-missing-in-the-proposed-c","errorCode":null,"errorMessage":"existing collection [%s] missing in the proposed collection configuration","messagePattern":"existing collection \\[(.+?)\\] missing in the proposed collection configuration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/scc.go","lineNumber":948,"sourceCode":"\t}\n\n\tproposedCollsMap := map[string]*pb.StaticCollectionConfig{}\n\tfor _, c := range proposedCollConfs {\n\t\tproposedCollsMap[c.Name] = c\n\t}\n\n\t// In the new collection config package, ensure that there is one entry per old collection. Any\n\t// number of new collections are allowed.\n\tfor _, committedCollConfig := range committedCollConfPkg.Config {\n\t\tcommittedColl := committedCollConfig.GetStaticCollectionConfig()\n\t\t// It cannot be nil\n\t\tif committedColl == nil {\n\t\t\treturn errors.Errorf(\"unknown collection configuration type\")\n\t\t}\n\n\t\tnewCollection, ok := proposedCollsMap[committedColl.Name]\n\t\tif !ok {\n\t\t\treturn errors.Errorf(\"existing collection [%s] missing in the proposed collection configuration\", committedColl.Name)\n\t\t}\n\n\t\tif newCollection.BlockToLive != committedColl.BlockToLive {\n\t\t\treturn errors.Errorf(\"the BlockToLive in an existing collection [%s] modified. Existing value [%d]\", committedColl.Name, committedColl.BlockToLive)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (i *Invocation) createOpaqueStates() ([]OpaqueState, error) {\n\tif i.ApplicationConfig == nil {\n\t\treturn nil, errors.Errorf(\"no application config for channel '%s'\", i.Stub.GetChannelID())\n\t}\n\torgs := i.ApplicationConfig.Organizations()\n\topaqueStates := make([]OpaqueState, 0, len(orgs))\n\tfor _, org := range orgs {\n\t\topaqueStates = append(opaqueStates, &ChaincodePrivateLedgerShim{\n\t\t\tCollection: implicitcollection.NameForOrg(org.MSPID()),","sourceCodeStart":930,"sourceCodeEnd":966,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/scc.go#L930-L966","documentation":"On chaincode upgrade, every previously committed collection must appear by name in the proposed collection config; new collections may be added but existing ones may not be dropped. This error names the committed collection that is absent from the proposal.","triggerScenarios":"Approving/committing an upgraded chaincode definition whose collection config omits one or more collections present in the committed definition (matched by collection Name).","commonSituations":"Renaming a collection (fabric does not allow it); trimming 'unused' collections during an upgrade; collection config rebuilt from a partial template.","solutions":["Include every existing collection (same name) in the new collection config, preserving BlockToLive.","Keep names identical — collections cannot be renamed or deleted across upgrades.","Fetch the committed collection config first and merge new collections into it rather than writing a fresh list.","Verify each entry's BlockToLive matches the committed value, which is also immutable."],"exampleFix":"// before: only new collection in upgrade JSON\n[{\"name\":\"newcoll\", ...}]\n// after: old collection retained + new one added\n[{\"name\":\"oldcoll\", \"block_to_live\": 0, ...}, {\"name\":\"newcoll\", ...}]","handlingStrategy":"validation","validationCode":"committedNames := map[string]bool{}\nfor _, c := range committedPkg.Config {\n  committedNames[c.GetStaticCollectionConfig().Name] = true\n}\nproposedNames := map[string]bool{}\nfor _, c := range proposed {\n  proposedNames[c.Name] = true\n}\nfor name := range committedNames {\n  if !proposedNames[name] {\n    return fmt.Errorf(\"collection %s must be retained in upgrade\", name)\n  }\n}","typeGuard":"func allCommittedRetained(committed, proposed []string) bool {\n  p := map[string]bool{}\n  for _, n := range proposed { p[n] = true }\n  for _, n := range committed { if !p[n] { return false } }\n  return true\n}","tryCatchPattern":"if err := commit(...); err != nil {\n  if strings.Contains(err.Error(), \"missing in the proposed collection configuration\") {\n    // add the named existing collection back into the config and resubmit\n  }\n  return err\n}","preventionTips":["Merge new collections into the committed set; never author a fresh list on upgrade.","Never rename or remove existing collections — fabric forbids both.","Preserve BlockToLive values exactly as committed.","Diff proposed vs committed collection names before every upgrade."],"tags":["fabric","private-data","chaincode-upgrade","collection-config"],"backgroundTag":"existing-collection-missing","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"}