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 nil

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. 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.
  2. Regenerate the config update from a valid base config instead of hand-editing, so mod_policy values match existing policies.
  3. Fix the existing channel config via a correct update that redefines or renames the missing policy before modifying the affected item.
  4. 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

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


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