{"record":{"id":"493de99632e4c84c","repo":"hyperledger/fabric","slug":"cannot-enable-application-capabilities-without-ord","errorCode":null,"errorMessage":"cannot enable application capabilities without orderer support first","messagePattern":"cannot enable application capabilities without orderer support first","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/channelconfig/bundle.go","lineNumber":250,"sourceCode":"\nfunc preValidate(config *cb.Config) error {\n\tif config == nil {\n\t\treturn errors.New(\"channelconfig Config cannot be nil\")\n\t}\n\n\tif config.ChannelGroup == nil {\n\t\treturn errors.New(\"config must contain a channel group\")\n\t}\n\n\tif og, ok := config.ChannelGroup.Groups[OrdererGroupKey]; ok {\n\t\tif _, ok := og.Values[CapabilitiesKey]; !ok {\n\t\t\tif _, ok := config.ChannelGroup.Values[CapabilitiesKey]; ok {\n\t\t\t\treturn errors.New(\"cannot enable channel capabilities without orderer support first\")\n\t\t\t}\n\n\t\t\tif ag, ok := config.ChannelGroup.Groups[ApplicationGroupKey]; ok {\n\t\t\t\tif _, ok := ag.Values[CapabilitiesKey]; ok {\n\t\t\t\t\treturn errors.New(\"cannot enable application capabilities without orderer support first\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":232,"sourceCodeEnd":258,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/channelconfig/bundle.go#L232-L258","documentation":"Same ordering rule as channel capabilities, applied to the application group: application capabilities may only be enabled after the orderer group already carries a capability entry. preValidate rejects a config where ApplicationGroup.Values[CapabilitiesKey] exists but the Orderer group's Values lack CapabilitiesKey, protecting older orderers from app-level config they cannot understand.","triggerScenarios":"A config update adds an application capability (e.g. V1_3/V2_0) under config.ChannelGroup.Groups[ApplicationGroupKey].Values while Groups[OrdererGroupKey].Values contains no CapabilitiesKey — e.g. one-shot upgrade generated by configtxgen with only Application.Capabilities set.","commonSituations":"Upgrading application channels during a v1.x→v2.x migration and skipping the orderer-group step; configtx.yaml where Channel/Application capabilities are set but Orderer capabilities are commented out; tooling that copies application config into a new channel without orderer capabilities.","solutions":["Submit an update enabling the capability in the Orderer group first, then enable the application capability in a second update","Set Orderer: Capabilities in configtx.yaml to a version >= the application capability's requirement and regenerate","Verify with configtxlator that groups.Orderer.values.Capabilities exists in the current config before crafting the app-capability delta"],"exampleFix":"// before\ndelta.Groups[\"Application\"].Values[\"Capabilities\"] = appCaps // rejected: no orderer caps\n\n// after\nog := delta.Groups[\"Orderer\"]\nog.Values[\"Capabilities\"] = ordererCaps // step 1: enable orderer capability first\ndelta.Groups[\"Application\"].Values[\"Capabilities\"] = appCaps // step 2: then app capability","handlingStrategy":"validation","validationCode":"func appCapsAllowed(cfg *cb.Config) bool {\n    if cfg.ChannelGroup == nil { return true }\n    ag, hasApp := cfg.ChannelGroup.Groups[\"Application\"]\n    _, hasAppCaps := map[string]*cb.ConfigValue{}, false\n    if hasApp && ag.Values != nil {\n        _, hasAppCaps = ag.Values[\"Capabilities\"]\n    }\n    if !hasAppCaps { return true }\n    og, ok := cfg.ChannelGroup.Groups[\"Orderer\"]\n    return ok && og.Values != nil && og.Values[\"Capabilities\"] != nil\n}","typeGuard":null,"tryCatchPattern":"if err := updateChannelConfig(cfg); err != nil {\n    if strings.Contains(err.Error(), \"cannot enable application capabilities\") {\n        return fmt.Errorf(\"submit orderer-group capability update before application capability\")\n    }\n    return err\n}","preventionTips":["Never enable application capabilities in a network whose orderer group lacks any capability entry","Generate upgrade deltas with configtxgen from a configtx.yaml whose Orderer capabilities are already set","Verify current orderer capabilities via configtxlator before proposing app-capability changes"],"tags":["fabric","channelconfig","capabilities","upgrade","application"],"backgroundTag":"capability-order-violation","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"}