{"record":{"id":"0622ec3027854509","repo":"hyperledger/fabric","slug":"invalid-key-for-the-collection-of-chaincode-s-s","errorCode":null,"errorMessage":"invalid key for the collection of chaincode %s:%s; expected '%s', received '%s'","messagePattern":"invalid key for the collection of chaincode (.+?):(.+?); expected '(.+?)', received '(.+?)'","errorType":"validation","errorClass":"VSCCEndorsementPolicyError","httpStatus":null,"severity":"error","filePath":"core/handlers/validation/builtin/v12/validation_logic.go","lineNumber":390,"sourceCode":"\t/********************************************/\n\t// there can only be one or two writes\n\tif len(lsccrwset.Writes) > 2 {\n\t\treturn policyErr(fmt.Errorf(\"LSCC can only issue one or two putState upon deploy\"))\n\t}\n\n\t/**********************************************************/\n\t/* security check 0.b - validation of the collection data */\n\t/**********************************************************/\n\tvar collectionsConfigArg []byte\n\tif len(lsccArgs) > 5 {\n\t\tcollectionsConfigArg = lsccArgs[5]\n\t}\n\n\tvar collectionsConfigLedger []byte\n\tif len(lsccrwset.Writes) == 2 {\n\t\tkey := privdata.BuildCollectionKVSKey(cdRWSet.Name)\n\t\tif lsccrwset.Writes[1].Key != key {\n\t\t\treturn policyErr(fmt.Errorf(\"invalid key for the collection of chaincode %s:%s; expected '%s', received '%s'\",\n\t\t\t\tcdRWSet.Name, cdRWSet.Version, key, lsccrwset.Writes[1].Key))\n\t\t}\n\n\t\tcollectionsConfigLedger = lsccrwset.Writes[1].Value\n\t}\n\n\tif !bytes.Equal(collectionsConfigArg, collectionsConfigLedger) {\n\t\treturn policyErr(fmt.Errorf(\"collection configuration arguments supplied for chaincode %s:%s do not match the configuration in the lscc writeset\",\n\t\t\tcdRWSet.Name, cdRWSet.Version))\n\t}\n\n\tchannelState, err := vscc.stateFetcher.FetchState()\n\tif err != nil {\n\t\treturn &commonerrors.VSCCExecutionFailureError{Err: fmt.Errorf(\"failed obtaining query executor: %v\", err)}\n\t}\n\tdefer channelState.Done()\n\n\tstate := &state{channelState}","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/handlers/validation/builtin/v12/validation_logic.go#L372-L408","documentation":"During LSCC (lifecycle system chaincode) validation, VSCC expects exactly two writes in the lscc rwset for a deploy: the chaincode definition and the collection configuration, keyed via privdata.BuildCollectionKVSKey(chaincodeName). This error means the key of the second write does not equal the expected '~collection<name>' key format. It indicates a malformed or hand-crafted lscc writeset, so the transaction is rejected as a policy error.","triggerScenarios":"Deploying (instantiating) a chaincode with collections where the lscc rwset's second write key was not generated by privdata.BuildCollectionKVSKey(cdRWSet.Name) — e.g. the proposal's collectionConfig was marshaled under a wrong or legacy key format, the write order differs (collection config is not Writes[1]), or a malicious/buggy client submits a forged lscc writeset.","commonSituations":"Custom or modified lifecycle tooling writing collection config directly to lscc instead of going through the standard instantiate/invoke path; chaincode names containing characters that make the collection key mismatch; clients targeting a different Fabric version whose key scheme changed; forged transactions caught by endorsement-policy validation.","solutions":["Ensure the deploy goes through the standard SDK/peer instantiate path (chaincode.Invoke with type 'deploy' plus the collection configuration argument) so lscc itself builds the collection key with privdata.BuildCollectionKVSKey.","Verify the lscc rwset contains exactly two writes with the collection config as the second write under key '~collection<chaincodeName>'.","Check that the chaincode name used in the collection config matches the name in the chaincode data (cdRWSet.Name); a mismatch yields a different expected key.","If running custom validation, confirm peer/VSCC versions match across the network (v1.2 validation logic vs older key formats)."],"exampleFix":"// before: custom tool writes collection config under wrong key\nlsccrwset.Writes[1].Key = chaincodeName + \"~collection\"\n// after: build the key the way lscc does\nlsccrwset.Writes[1].Key = privdata.BuildCollectionKVSKey(cdRWSet.Name)","handlingStrategy":"validation","validationCode":"// Before submitting an lscc deploy writeset, assert the collection key matches\nimport \"github.com/hyperledger/fabric/core/common/privdata\"\nfunc validateCollectionKey(chaincodeName string, writes []*kvrwset.KVWrite) error {\n  if len(writes) != 2 {\n    return fmt.Errorf(\"expected 2 lscc writes, got %d\", len(writes))\n  }\n  expected := privdata.BuildCollectionKVSKey(chaincodeName)\n  if writes[1].Key != expected {\n    return fmt.Errorf(\"collection key mismatch: expected %q, got %q\", expected, writes[1].Key)\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always deploy collections via the standard peer instantiate/upgrade command or SDK lifecycle APIs, never by hand-writing lscc writesets","Use privdata.BuildCollectionKVSKey to compute collection keys whenever constructing or inspecting lscc writes","Keep all peers at the same Fabric version so the collection key scheme is consistent across the network"],"tags":["fabric","vscc","lscc","collections","validation"],"backgroundTag":"lscc-writeset-key-mismatch","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"}