hyperledger/fabric · error

cannot use _lifecycle without V2_0 application capabilities

Error message

cannot use _lifecycle without V2_0 application capabilities enabled for channel '%s'

What it means

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.

Source

Thrown at core/chaincode/lifecycle/cache.go:346

	// between HandleStateUpdate and StateCommitDone, it's possible (in fact likely)
	// that a chaincode invocation will acquire a read-lock on the world state, then attempt
	// to get chaincode info from the cache, resulting in a deadlock.  So, we choose
	// potential inconsistency between the cache and the world state which the callers
	// must detect and cope with as necessary.  Note, the cache will always be _at least_
	// as current as the committed state.
	c.eventBroker.ApproveOrDefineCommitted(channelName)
}

// ChaincodeInfo returns the chaincode definition and its install info.
// An error is returned only if either the channel or the chaincode do not exist.
func (c *Cache) ChaincodeInfo(channelID, name string) (*LocalChaincodeInfo, error) {
	if name == LifecycleNamespace {
		ac, ok := c.Resources.ChannelConfigSource.GetStableChannelConfig(channelID).ApplicationConfig()
		if !ok {
			return nil, errors.Errorf("application config does not exist for channel '%s'", channelID)
		}
		if !ac.Capabilities().LifecycleV20() {
			return nil, errors.Errorf("cannot use _lifecycle without V2_0 application capabilities enabled for channel '%s'", channelID)
		}
		return c.getLifecycleSCCChaincodeInfo(channelID)
	}

	c.mutex.RLock()
	defer c.mutex.RUnlock()
	channelChaincodes, ok := c.definedChaincodes[channelID]
	if !ok {
		return nil, errors.Errorf("unknown channel '%s'", channelID)
	}

	cachedChaincode, ok := channelChaincodes.Chaincodes[name]
	if !ok {
		return nil, errors.Errorf("unknown chaincode '%s' for channel '%s'", name, channelID)
	}

	return &LocalChaincodeInfo{
		Definition:  cachedChaincode.Definition,

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Enable V2_0 (or later) application capabilities via a channel config update (Application: Capabilities: V2_0).
  2. In configtx.yaml set Capabilities.Application to V2_0 and regenerate the channel creation/update transaction.
  3. Ensure all peers and orderers are upgraded to a version supporting V2_0 capabilities before flipping the flag.
  4. If you must stay on V1_x, use the legacy LSCC lifecycle instead of _lifecycle queries.

Example fix

// configtx.yaml - before
Application:
  Capabilities:
    V1_4_3: true
// after
Application:
  Capabilities:
    V2_0: true
Defensive patterns

Strategy: validation

Validate before calling

ac, ok := configSource.GetStableChannelConfig(channelID).ApplicationConfig()
if !ok || !ac.Capabilities().LifecycleV20() {
    return fmt.Errorf("channel %s must enable V2_0 application capabilities for _lifecycle", channelID)
}

Try / catch

info, err := cache.ChaincodeInfo(channelID, "_lifecycle")
if err != nil && strings.Contains(err.Error(), "V2_0 application capabilities") {
    return fmt.Errorf("upgrade channel %s to V2_0 app capabilities first: %w", channelID, err)
}

Prevention

When it happens

Trigger: 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+.

Common situations: 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.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/50af0cdba11e4c59. Report an issue: GitHub.