hyperledger/fabric · error

existing collection [ ] missing in the proposed collection…

Error message

existing collection [%s] missing in the proposed collection configuration

What it means

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.

Solutions

  1. Include every existing collection (same name) in the new collection config, preserving BlockToLive.
  2. Keep names identical — collections cannot be renamed or deleted across upgrades.
  3. Fetch the committed collection config first and merge new collections into it rather than writing a fresh list.
  4. Verify each entry's BlockToLive matches the committed value, which is also immutable.

Example fix

// before: only new collection in upgrade JSON
[{"name":"newcoll", ...}]
// after: old collection retained + new one added
[{"name":"oldcoll", "block_to_live": 0, ...}, {"name":"newcoll", ...}]
Defensive patterns

Strategy: validation

Validate before calling

committedNames := map[string]bool{}
for _, c := range committedPkg.Config {
  committedNames[c.GetStaticCollectionConfig().Name] = true
}
proposedNames := map[string]bool{}
for _, c := range proposed {
  proposedNames[c.Name] = true
}
for name := range committedNames {
  if !proposedNames[name] {
    return fmt.Errorf("collection %s must be retained in upgrade", name)
  }
}

Type guard

func allCommittedRetained(committed, proposed []string) bool {
  p := map[string]bool{}
  for _, n := range proposed { p[n] = true }
  for _, n := range committed { if !p[n] { return false } }
  return true
}

Try / catch

if err := commit(...); err != nil {
  if strings.Contains(err.Error(), "missing in the proposed collection configuration") {
    // add the named existing collection back into the config and resubmit
  }
  return err
}

Prevention

When it happens

Trigger: Approving/committing an upgraded chaincode definition whose collection config omits one or more collections present in the committed definition (matched by collection Name).

Common situations: Renaming a collection (fabric does not allow it); trimming 'unused' collections during an upgrade; collection config rebuilt from a partial template.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/e48b8537defaaf04. Report an issue: GitHub.

Appendix: source

Thrown at core/chaincode/lifecycle/scc.go:948

	}

	proposedCollsMap := map[string]*pb.StaticCollectionConfig{}
	for _, c := range proposedCollConfs {
		proposedCollsMap[c.Name] = c
	}

	// In the new collection config package, ensure that there is one entry per old collection. Any
	// number of new collections are allowed.
	for _, committedCollConfig := range committedCollConfPkg.Config {
		committedColl := committedCollConfig.GetStaticCollectionConfig()
		// It cannot be nil
		if committedColl == nil {
			return errors.Errorf("unknown collection configuration type")
		}

		newCollection, ok := proposedCollsMap[committedColl.Name]
		if !ok {
			return errors.Errorf("existing collection [%s] missing in the proposed collection configuration", committedColl.Name)
		}

		if newCollection.BlockToLive != committedColl.BlockToLive {
			return errors.Errorf("the BlockToLive in an existing collection [%s] modified. Existing value [%d]", committedColl.Name, committedColl.BlockToLive)
		}
	}
	return nil
}

func (i *Invocation) createOpaqueStates() ([]OpaqueState, error) {
	if i.ApplicationConfig == nil {
		return nil, errors.Errorf("no application config for channel '%s'", i.Stub.GetChannelID())
	}
	orgs := i.ApplicationConfig.Organizations()
	opaqueStates := make([]OpaqueState, 0, len(orgs))
	for _, org := range orgs {
		opaqueStates = append(opaqueStates, &ChaincodePrivateLedgerShim{
			Collection: implicitcollection.NameForOrg(org.MSPID()),

View on GitHub (pinned to 2736b63f8f)