{"record":{"id":"50af0cdba11e4c59","repo":"hyperledger/fabric","slug":"cannot-use-lifecycle-without-v2-0-application-cap","errorCode":null,"errorMessage":"cannot use _lifecycle without V2_0 application capabilities enabled for channel '%s'","messagePattern":"cannot use _lifecycle without V2_0 application capabilities enabled for channel '(.+?)'","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/cache.go","lineNumber":346,"sourceCode":"\t// between HandleStateUpdate and StateCommitDone, it's possible (in fact likely)\n\t// that a chaincode invocation will acquire a read-lock on the world state, then attempt\n\t// to get chaincode info from the cache, resulting in a deadlock.  So, we choose\n\t// potential inconsistency between the cache and the world state which the callers\n\t// must detect and cope with as necessary.  Note, the cache will always be _at least_\n\t// as current as the committed state.\n\tc.eventBroker.ApproveOrDefineCommitted(channelName)\n}\n\n// ChaincodeInfo returns the chaincode definition and its install info.\n// An error is returned only if either the channel or the chaincode do not exist.\nfunc (c *Cache) ChaincodeInfo(channelID, name string) (*LocalChaincodeInfo, error) {\n\tif name == LifecycleNamespace {\n\t\tac, ok := c.Resources.ChannelConfigSource.GetStableChannelConfig(channelID).ApplicationConfig()\n\t\tif !ok {\n\t\t\treturn nil, errors.Errorf(\"application config does not exist for channel '%s'\", channelID)\n\t\t}\n\t\tif !ac.Capabilities().LifecycleV20() {\n\t\t\treturn nil, errors.Errorf(\"cannot use _lifecycle without V2_0 application capabilities enabled for channel '%s'\", channelID)\n\t\t}\n\t\treturn c.getLifecycleSCCChaincodeInfo(channelID)\n\t}\n\n\tc.mutex.RLock()\n\tdefer c.mutex.RUnlock()\n\tchannelChaincodes, ok := c.definedChaincodes[channelID]\n\tif !ok {\n\t\treturn nil, errors.Errorf(\"unknown channel '%s'\", channelID)\n\t}\n\n\tcachedChaincode, ok := channelChaincodes.Chaincodes[name]\n\tif !ok {\n\t\treturn nil, errors.Errorf(\"unknown chaincode '%s' for channel '%s'\", name, channelID)\n\t}\n\n\treturn &LocalChaincodeInfo{\n\t\tDefinition:  cachedChaincode.Definition,","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/cache.go#L328-L364","documentation":"Thrown by Cache.ChaincodeInfo when the queried chaincode is _lifecycle but the channel's application capabilities are below V2_0 (LifecycleV20() returns false). The new _lifecycle system chaincode and its cache path are only valid when the V2_0 application capability is enabled on the channel.","triggerScenarios":"Calling ChaincodeInfo(channelID, \"_lifecycle\") on a channel whose Application capabilities group is set to V1_x (e.g. V1_4_2) instead of V2_0+.","commonSituations":"Channels upgraded from Fabric 1.4 without updating the capabilities in the application group; mixed-version network where application group capability was not bumped; configtx.yaml still specifying an old capability.","solutions":["Enable V2_0 (or later) application capabilities via a channel config update (Application: Capabilities: V2_0).","In configtx.yaml set Capabilities.Application to V2_0 and regenerate the channel creation/update transaction.","Ensure all peers and orderers are upgraded to a version supporting V2_0 capabilities before flipping the flag.","If you must stay on V1_x, use the legacy LSCC lifecycle instead of _lifecycle queries."],"exampleFix":"// configtx.yaml - before\nApplication:\n  Capabilities:\n    V1_4_3: true\n// after\nApplication:\n  Capabilities:\n    V2_0: true","handlingStrategy":"validation","validationCode":"ac, ok := configSource.GetStableChannelConfig(channelID).ApplicationConfig()\nif !ok || !ac.Capabilities().LifecycleV20() {\n    return fmt.Errorf(\"channel %s must enable V2_0 application capabilities for _lifecycle\", channelID)\n}","typeGuard":null,"tryCatchPattern":"info, err := cache.ChaincodeInfo(channelID, \"_lifecycle\")\nif err != nil && strings.Contains(err.Error(), \"V2_0 application capabilities\") {\n    return fmt.Errorf(\"upgrade channel %s to V2_0 app capabilities first: %w\", channelID, err)\n}","preventionTips":["Set Capabilities.Application: V2_0 in configtx.yaml for all new channels.","Upgrade legacy 1.4 channels' application capabilities before using _lifecycle.","Upgrade all nodes before flipping capability flags; verify with 'peer channel getinfo' flows."],"tags":["fabric","capabilities","lifecycle-v2"],"backgroundTag":"capability-not-enabled","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"}