hyperledger/fabric · error

existing collection [%s] 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.

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)

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.