hyperledger/fabric · error
ConfigValue not found at value path: %s
Error message
ConfigValue not found at value path: %s
What it means
When a 'values/<path>/<key>' entry is found, its comparable must wrap a real cb.ConfigValue. This error means the entry exists under a value path but comparable.ConfigValue is nil — the wrong union member (or an empty comparable) was stored at that key. It is thrown immediately before cloning the value into the reconstructed ConfigGroup.
Source
Thrown at common/configtx/configmap.go:141
newConfigGroup := protoutil.NewConfigGroup()
proto.Merge(newConfigGroup, group.ConfigGroup)
for key := range group.Groups {
updatedGroup, err := recurseConfigMap(path+pathSeparator+key, configMap)
if err != nil {
return nil, err
}
newConfigGroup.Groups[key] = updatedGroup
}
for key := range group.Values {
valuePath := valuePrefix + path + pathSeparator + key
value, ok := configMap[valuePath]
if !ok {
return nil, errors.Errorf("missing value at path: %s", valuePath)
}
if value.ConfigValue == nil {
return nil, errors.Errorf("ConfigValue not found at value path: %s", valuePath)
}
newConfigGroup.Values[key] = proto.Clone(value.ConfigValue).(*cb.ConfigValue)
}
for key := range group.Policies {
policyPath := policyPrefix + path + pathSeparator + key
policy, ok := configMap[policyPath]
if !ok {
return nil, errors.Errorf("missing policy at path: %s", policyPath)
}
if policy.ConfigPolicy == nil {
return nil, errors.Errorf("ConfigPolicy not found at policy path: %s", policyPath)
}
newConfigGroup.Policies[key] = proto.Clone(policy.ConfigPolicy).(*cb.ConfigPolicy)
logger.Debugf("Setting policy for key %s to %+v", key, group.Policies[key])
}
// This is a really very hacky fix to facilitate upgrading channels which were constructedView on GitHub (pinned to 2736b63f8f)
Solutions
- Store comparable{ConfigValue: ...} for every 'values/...' key in the map.
- Prefer configtx.NewComparableConfig over manual map construction to keep kinds and prefixes aligned.
- Audit any helper that builds comparables and assert the payload kind matches the key prefix.
- Dump the comparable at the reported path to identify which wrong member was set.
Example fix
// before
configMap["values/Orderer/values/BatchSize"] = comparable{ConfigPolicy: policy}
// after
configMap["values/Orderer/values/BatchSize"] = comparable{ConfigValue: batchSizeValue} Defensive patterns
Strategy: validation
Validate before calling
func valueEntryIsValue(configMap map[string]configtx.Comparable, path, key string) bool {
c, ok := configMap["values/"+path+"/"+key]
return ok && c.ConfigValue != nil
} Type guard
func asConfigValue(c comparable) (*cb.ConfigValue, bool) {
if c.ConfigValue == nil {
return nil, false
}
return c.ConfigValue, true
} Try / catch
// errors are returned, not panicked
config, err := configtx.ConfigMapToConfig(configMap)
if err != nil {
return fmt.Errorf("non-value payload under value path: %w", err)
} Prevention
- Store ConfigValue payloads under 'values/' keys only
- Prefer configtx.NewComparableConfig over manual comparable construction
- Assert payload-kind/prefix consistency in unit tests for map builders
When it happens
Trigger: recurseConfigMap finding a configMap entry at the computed valuePath whose ConfigValue field is nil — e.g. a ConfigGroup or ConfigPolicy stored under a 'values/...' key, or a zero-value comparable placeholder.
Common situations: Prefix/kind mismatches when constructing the map manually; code that inserts comparables without setting the payload; shared map building utilities reused across kinds with wrong arguments.
Related errors
- missing value at path: %s
- Attempted to set the batch size max message count to an inva
- Attempted to set the batch size absolute max bytes to an inv
- Attempted to set the batch size preferred max bytes to an in
- Attempted to set the batch size preferred max bytes (%v) gre
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/2c19b3359eda1ea0.
Report an issue: GitHub.