{"record":{"id":"b50bee05286c395e","repo":"hyperledger/fabric","slug":"missing-policy-at-path-s","errorCode":null,"errorMessage":"missing policy at path: %s","messagePattern":"missing policy at path: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/configtx/configmap.go","lineNumber":150,"sourceCode":"\t}\n\n\tfor key := range group.Values {\n\t\tvaluePath := valuePrefix + path + pathSeparator + key\n\t\tvalue, ok := configMap[valuePath]\n\t\tif !ok {\n\t\t\treturn nil, errors.Errorf(\"missing value at path: %s\", valuePath)\n\t\t}\n\t\tif value.ConfigValue == nil {\n\t\t\treturn nil, errors.Errorf(\"ConfigValue not found at value path: %s\", valuePath)\n\t\t}\n\t\tnewConfigGroup.Values[key] = proto.Clone(value.ConfigValue).(*cb.ConfigValue)\n\t}\n\n\tfor key := range group.Policies {\n\t\tpolicyPath := policyPrefix + path + pathSeparator + key\n\t\tpolicy, ok := configMap[policyPath]\n\t\tif !ok {\n\t\t\treturn nil, errors.Errorf(\"missing policy at path: %s\", policyPath)\n\t\t}\n\t\tif policy.ConfigPolicy == nil {\n\t\t\treturn nil, errors.Errorf(\"ConfigPolicy not found at policy path: %s\", policyPath)\n\t\t}\n\t\tnewConfigGroup.Policies[key] = proto.Clone(policy.ConfigPolicy).(*cb.ConfigPolicy)\n\t\tlogger.Debugf(\"Setting policy for key %s to %+v\", key, group.Policies[key])\n\t}\n\n\t// This is a really very hacky fix to facilitate upgrading channels which were constructed\n\t// using the channel generation from v1.0 with bugs FAB-5309, and FAB-6080.\n\t// In summary, these channels were constructed with a bug which left mod_policy unset in some cases.\n\t// If mod_policy is unset, it's impossible to modify the element, and current code disallows\n\t// unset mod_policy values.  This hack 'fixes' existing config with empty mod_policy values.\n\t// If the capabilities framework is on, it sets any unset mod_policy to 'Admins'.\n\t// This code needs to sit here until validation of v1.0 channels is deprecated from the codebase.\n\tif _, ok := configMap[hackyFixOrdererCapabilities]; ok {\n\t\t// Hacky fix constants, used in recurseConfigMap\n\t\tif newConfigGroup.ModPolicy == \"\" {","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/configtx/configmap.go#L132-L168","documentation":"recurseConfigMap is converting a config tree back into a ConfigGroup and expects every policy listed in a group to have a corresponding entry in the flattened configMap keyed by its path. This error fires when group.Policies contains a key whose path (policyPrefix + path + key) is absent from the map. It indicates the configMap was built inconsistently with the group tree.","triggerScenarios":"Calling configMapToConfig on a config map that is missing a '<policyPrefix><groupPath>/<policyKey>' entry while the corresponding group still declares that policy in Policies.","commonSituations":"Hand-built or programmatically mutated config maps where a policy entry was removed or renamed but the group still references it; loading a truncated or corrupted channel configuration.","solutions":["Ensure every policy key in the group has a corresponding entry added as ConfigPolicy in the config map at path '<policyPrefix><groupPath>/<key>'.","Rebuild the config map from the original ConfigGroup via channel.Config instead of hand-assembling it.","Check the policyPrefix/path separator usage matches the internal pathSeparator convention."],"exampleFix":"// before\nconfigMap[\"/Channel/policies/Admins\"] = nil // policy entry missing\n// after\nconfigMap[\"/Channel/policies/Admins\"] = &Config{ConfigPolicy: &cb.ConfigPolicy{Policy: &cb.Policy{Type: int32(cb.Policy_SIGNATURE), Value: policyBytes}}}","handlingStrategy":"validation","validationCode":"for key := range group.Policies {\n  if _, ok := configMap[policyPrefix+path+pathSeparator+key]; !ok {\n    return fmt.Errorf(\"config map missing policy %s at %s\", key, path)\n  }\n}","typeGuard":"if p, ok := configMap[policyPath]; !ok || p == nil || p.ConfigPolicy == nil { return false }; return true","tryCatchPattern":"if err := recurseConfigMap(configMap, group, path, newGroup); err != nil {\n  if strings.Contains(err.Error(), \"missing policy at path\") {\n    // repair or rebuild config map and retry\n  }\n  return err\n}","preventionTips":["Always build config maps with the library's own helpers instead of custom path strings","Keep policyPrefix and pathSeparator usage consistent between writer and reader","Round-trip test: build map from config, then recurse back, before submitting"],"tags":["hyperledger-fabric","configtx","policy"],"backgroundTag":"missing-policy-path","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"}