hyperledger/fabric · error
unexpected missing policy %s for item %s
Error message
unexpected missing policy %s for item %s
What it means
During channel config update verification, verifyDeltaSet could not find the modification policy named by an existing config item's mod_policy. The validator needs this policy to check that the update signatures authorize the change; without it the update is rejected as malformed or corrupt. This usually means the existing config references a policy that does not exist in the current channel config.
Source
Thrown at common/configtx/update.go:93
if err := validateModPolicy(value.modPolicy()); err != nil {
return errors.Wrapf(err, "invalid mod_policy for element %s", key)
}
existing, ok := vi.configMap[key]
if !ok {
if value.version() != 0 {
return errors.Errorf("attempted to set key %s to version %d, but key does not exist", key, value.version())
}
continue
}
if value.version() != existing.version()+1 {
return errors.Errorf("attempt to set key %s to version %d, but key is at version %d", key, value.version(), existing.version())
}
policy, ok := vi.policyForItem(existing)
if !ok {
return errors.Errorf("unexpected missing policy %s for item %s", existing.modPolicy(), key)
}
// Ensure the policy is satisfied
if err := policy.EvaluateSignedData(signedData); err != nil {
logger.Warnw("policy not satisfied for channel configuration update", "key", key, "policy", policy, "signingIdenties", protoutil.LogMessageForSerializedIdentities(signedData))
return errors.Wrapf(err, "policy for %s not satisfied", key)
}
}
return nil
}
func verifyFullProposedConfig(writeSet, fullProposedConfig map[string]comparable) error {
for key := range writeSet {
if _, ok := fullProposedConfig[key]; !ok {
return errors.Errorf("writeset contained key %s which did not appear in proposed config", key)
}
}
return nilView on GitHub (pinned to 2736b63f8f)
Solutions
- Inspect the current channel config (configtxlator proto_decode) and ensure every item's mod_policy resolves to a policy defined at that item's group level.
- Regenerate the config update from a valid base config instead of hand-editing, so mod_policy values match existing policies.
- Fix the existing channel config via a correct update that redefines or renames the missing policy before modifying the affected item.
- Check for channel/group path mistakes: a policy named 'Admins' exists at some groups but not the group owning the item.
Example fix
// before: update item with mod_policy "Orderers/Admins" but that policy was removed // after: set item.mod_policy to an existing policy, e.g. "/Channel/Orderer/Admins", // or add the policy back to the config group before submitting the update
Defensive patterns
Strategy: validation
Validate before calling
// Validate every existing item's mod_policy resolves before proposing an update
func checkModPolicies(cfg *cb.Config, pm policies.PolicyManager) error {
return traverseConfigGroups(cfg.ChannelGroup, func(path string, g *cb.ConfigGroup) error {
for _, v := range g.Values {
if _, ok := pm.GetPolicy(v.ModPolicy); !ok {
return fmt.Errorf("item %s references missing mod_policy %s", path, v.ModPolicy)
}
}
return nil
})
} Try / catch
// wrap proposeConfigUpdate and detect the missing-policy family
if _, err := validator.ProposeConfigUpdate(env, seq); err != nil {
if strings.Contains(err.Error(), "unexpected missing policy") {
// fix config mod_policy references, rebuild update
}
return err
} Prevention
- Never hand-edit serialized channel config; always derive updates from configtxlator diffs of the live config.
- After any update that removes or renames a policy, audit remaining items' mod_policy references.
- Keep mod_policy names consistent with the standard group policies (Admins, Readers, Writers, Orderer).
When it happens
Trigger: Calling proposeConfigUpdate or Validate with a ConfigUpdateEnvelope whose writeSet modifies an item whose existing entry's mod_policy does not resolve to a policy in the channel's policy manager (e.g. policyForItem returns !ok).
Common situations: Hand-edited or tool-generated channel config referencing a mod_policy like 'Admins' under a path where the policy group was removed; upgrading from an older genesis block; a config item whose mod_policy was renamed or deleted in a prior update.
Related errors
- 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
- missing policy at path: %s
- ConfigPolicy not found at policy path: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/473e10df61cbaeb5.
Report an issue: GitHub.