{"record":{"id":"2be26d39c4e8b090","repo":"hyperledger/fabric","slug":"empty-collection-name-is-not-allowed-2be26d","errorCode":null,"errorMessage":"empty collection-name is not allowed","messagePattern":"empty collection-name is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/handlers/validation/builtin/v13/lscc_validation_logic.go","lineNumber":206,"sourceCode":"\t\t// Collection object itself is stored as value so that we can\n\t\t// check whether the block to live is changed -- FAB-7810\n\t\tnewCollectionsMap[newCollection.GetName()] = newCollection\n\t}\n\n\tif err := checkForMissingCollections(newCollectionsMap, oldCollectionConfigs); err != nil {\n\t\treturn err\n\t}\n\n\tif err := checkForModifiedCollectionsBTL(newCollectionsMap, oldCollectionConfigs); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc validateCollectionName(collectionName string) error {\n\tif collectionName == \"\" {\n\t\treturn fmt.Errorf(\"empty collection-name is not allowed\")\n\t}\n\tmatch := validCollectionNameRegex.FindString(collectionName)\n\tif len(match) != len(collectionName) {\n\t\treturn fmt.Errorf(\"collection-name: %s not allowed. A valid collection name follows the pattern: %s\",\n\t\t\tcollectionName, AllowedCharsCollectionName)\n\t}\n\treturn nil\n}\n\n// validateRWSetAndCollection performs validation of the rwset\n// of an LSCC deploy operation and then it validates any collection\n// configuration\nfunc (vscc *Validator) validateRWSetAndCollection(\n\tlsccrwset *kvrwset.KVRWSet,\n\tcdRWSet *ccprovider.ChaincodeData,\n\tlsccArgs [][]byte,\n\tlsccFunc string,\n\tac vc.Capabilities,","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/handlers/validation/builtin/v13/lscc_validation_logic.go#L188-L224","documentation":"validateCollectionName rejects a private data collection whose name is the empty string. Collection names identify the collection in state metadata and gossip, so an empty name is invalid before any regex check is applied.","triggerScenarios":"Submitting a collection config where a StaticCollectionConfig has Name == \"\", via lifecycle --collections-config or a programmatically built CollectionConfigPackage.","commonSituations":"Building collection configs programmatically and leaving the Name field unset; JSON with {\"name\": \"\"}; deserialization that drops an empty field.","solutions":["Set a non-empty collection name in every StaticCollectionConfig entry","Validate the collections JSON before submission: each entry must have a name matching the allowed-characters pattern","Use the fabric CLI's collections-config parser locally to catch empty names early"],"exampleFix":"// before\n{\"name\": \"\", \"policy\": \"OR('Org1MSP.peer')\"}\n// after\n{\"name\": \"collectionOne\", \"policy\": \"OR('Org1MSP.peer')\"}","handlingStrategy":"validation","validationCode":"function validateCollectionName(name) {\n  if (!name || name.length === 0) {\n    throw new Error('empty collection-name is not allowed');\n  }\n}","typeGuard":"function hasCollectionName(c) {\n  return typeof c.name === 'string' && c.name.length > 0;\n}","tryCatchPattern":"try {\n  await contract.submitTransaction('DeployChaincode', ...args);\n} catch (err) {\n  if (String(err).includes('empty collection-name')) {\n    // set a valid name on every collection entry\n  }\n  throw err;\n}","preventionTips":["Require a name field in the collections-config schema and reject empty strings","Avoid leaving protobuf Name fields unset when building configs in code","Lint collections JSON before every deploy/upgrade"],"tags":["hyperledger-fabric","private-data","collection-name","validation"],"backgroundTag":"invalid-collection-name","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"}