hyperledger/fabric · error

could not find policy %s

Error message

could not find policy %s

What it means

consenterVerifier.Evaluate looks up the '/Channel/Orderer/Writers' policy via the channel's policy manager and returns this error when the policy is not registered. Without the Writers policy the verifier cannot authenticate that the signature came from an authorized orderer writer.

Source

Thrown at orderer/consensus/smartbft/verifier.go:455

	if !proto.Equal(ordererMDFromBlock, ordererMD) {
		return errors.Errorf("signature's OrdererBlockMetadata and OrdererBlockMetadata extracted from block do not match")
	}

	return nil
}

type consenterVerifier struct {
	logger        *flogging.FabricLogger
	channel       string
	policyManager policies.Manager
}

// Evaluate evaluates signed data and returns no error if signature is valid and satisfies the policy
func (cv *consenterVerifier) Evaluate(signatureSet []*protoutil.SignedData) error {
	policy, ok := cv.policyManager.GetPolicy(policies.ChannelOrdererWriters)
	if !ok {
		cv.logger.Errorf("[%s] Error: could not find policy %s in policy manager %v", cv.channel, policies.ChannelOrdererWriters, cv.policyManager)
		return errors.Errorf("could not find policy %s", policies.ChannelOrdererWriters)
	}

	if cv.logger.IsEnabledFor(zapcore.DebugLevel) {
		cv.logger.Debugf("== Evaluating %T Policy %s ==", policy, policies.ChannelOrdererWriters)
		defer cv.logger.Debugf("== Done Evaluating %T Policy %s", policy, policies.ChannelOrdererWriters)
	}

	return policy.EvaluateSignedData(signatureSet)
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the channel's config contains a valid Orderer/Writers policy (check the channel config transaction)
  2. Ensure the verifier is constructed with the policy manager for the correct, fully-initialized channel
  3. Restore a known-good channel config (latest config block) if a bad update removed the policy
  4. Enable orderer debug logs to inspect which policy manager was passed to consenterVerifier

Example fix

// before: verifier built with an empty/in-progress manager
verifier := newVerifier(pm, ...) // pm has no policies yet
// after: wait for channel config load and check first
policy, ok := pm.GetPolicy(policies.ChannelOrdererWriters)
if !ok {
    return fmt.Errorf("writers policy missing from channel %s", chID)
}
Defensive patterns

Strategy: validation

Validate before calling

pm := verifierPolicyManager(channelID)
policy, ok := pm.GetPolicy(policies.ChannelOrdererWriters)
if !ok {
    return fmt.Errorf("channel %s is missing %s policy; check channel config", channelID, policies.ChannelOrdererWriters)
}

Type guard

func hasWritersPolicy(pm policies.PolicyManager) bool {
    _, ok := pm.GetPolicy(policies.ChannelOrdererWriters)
    return ok
}

Try / catch

if err := cv.Evaluate(signatureSet); err != nil {
    if strings.Contains(err.Error(), "could not find policy") {
        log.Errorf("writers policy missing; reloading channel config for %s", cv.channel)
        return reloadChannelConfig(cv.channel)
    }
    return err
}

Prevention

When it happens

Trigger: Evaluate (called during VerifyConsenterSig signature-set evaluation) runs against a policyManager that does not contain policies.ChannelOrdererWriters — typically an uninitialized, stale, or wrong-channel policy manager.

Common situations: Channel config missing or mis-formed Orderer/Writers policy; verifier created before channel config was loaded; chaincode/system code wiring the wrong policy manager; config update removed the policy.

Related errors


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