hyperledger/fabric · error
Collections do not match
Error message
Collections do not match
What it means
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.
Source
Thrown at core/chaincode/lifecycle/lifecycle.go:136
EndorsementInfo *lb.ChaincodeEndorsementInfo
ValidationInfo *lb.ChaincodeValidationInfo
Collections *pb.CollectionConfigPackage
}
func (cp *ChaincodeParameters) Equal(ocp *ChaincodeParameters) error {
switch {
case cp.EndorsementInfo.Version != ocp.EndorsementInfo.Version:
return errors.Errorf("expected Version '%s' does not match passed Version '%s'", cp.EndorsementInfo.Version, ocp.EndorsementInfo.Version)
case cp.EndorsementInfo.EndorsementPlugin != ocp.EndorsementInfo.EndorsementPlugin:
return errors.Errorf("expected EndorsementPlugin '%s' does not match passed EndorsementPlugin '%s'", cp.EndorsementInfo.EndorsementPlugin, ocp.EndorsementInfo.EndorsementPlugin)
case cp.EndorsementInfo.InitRequired != ocp.EndorsementInfo.InitRequired:
return errors.Errorf("expected InitRequired '%t' does not match passed InitRequired '%t'", cp.EndorsementInfo.InitRequired, ocp.EndorsementInfo.InitRequired)
case cp.ValidationInfo.ValidationPlugin != ocp.ValidationInfo.ValidationPlugin:
return errors.Errorf("expected ValidationPlugin '%s' does not match passed ValidationPlugin '%s'", cp.ValidationInfo.ValidationPlugin, ocp.ValidationInfo.ValidationPlugin)
case !bytes.Equal(cp.ValidationInfo.ValidationParameter, ocp.ValidationInfo.ValidationParameter):
return errors.Errorf("expected ValidationParameter '%x' does not match passed ValidationParameter '%x'", cp.ValidationInfo.ValidationParameter, ocp.ValidationInfo.ValidationParameter)
case !proto.Equal(cp.Collections, ocp.Collections):
return errors.Errorf("Collections do not match")
default:
}
return nil
}
// ChaincodeDefinition contains the chaincode parameters, as well as the sequence number of the definition.
// Note, it does not embed ChaincodeParameters so as not to complicate the serialization. It is expected
// that any instance will have no nil fields once initialized.
// WARNING: This structure is serialized/deserialized from the DB, re-ordering or adding fields
// will cause opaque checks to fail.
type ChaincodeDefinition struct {
Sequence int64
EndorsementInfo *lb.ChaincodeEndorsementInfo
ValidationInfo *lb.ChaincodeValidationInfo
Collections *pb.CollectionConfigPackage
}
type ApprovedChaincodeDefinition struct {View on GitHub (pinned to 2736b63f8f)
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)
Example fix
// before
collections: {newCollection added}, sequence: 1 // committed had original collections
// after
original collections, sequence: 1 // or sequence: 2 with the new collection Defensive patterns
Strategy: validation
Validate before calling
committed, err := lifecycle.QueryChaincodeDefinition(chname, ccname, publicState)
if err == nil && !proto.Equal(newDef.Collections, committed.Collections) && newDef.Sequence == committed.Sequence {
return fmt.Errorf("collections change requires sequence bump")
} Type guard
func sameCollections(a, b *lifecycle.ChaincodeParameters) bool {
return a != nil && b != nil && proto.Equal(a.Collections, b.Collections)
} Try / catch
if err := params.Equal(committedParams); err != nil {
if strings.Contains(err.Error(), "Collections do not match") {
// reuse committed collections config or bump sequence
}
return err
} Prevention
- 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
When it happens
Trigger: Committing a definition whose CollectionConfigPackage differs (added/removed/modified collections) from the committed definition at the same sequence number.
Common situations: 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.
Related errors
- private data APIs are not allowed in chaincode Init()
- failed listing installed chaincodes
- failed to parse collection config
- [channel %s] failed to get chaincode container info for %s
- chaincode '%s' does not require initialization but called as
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/9eeccfb6a4705984.
Report an issue: GitHub.