hyperledger/fabric · error

policy (name='%s',type='%T') is not convertible to Signature

Error message

policy (name='%s',type='%T') is not convertible to SignaturePolicyEnvelope

What it means

PolicyLogger.Convert converts a policy back into a SignaturePolicyEnvelope for signature collection (e.g. building config signatures). If the wrapped policy does not implement the Converter interface, conversion is impossible and this error names the policy and its concrete Go type.

Source

Thrown at common/policies/policy.go:316

		defer logger.Debugf("== Done Evaluating %T Policy %s", pl.Policy, pl.policyName)
	}

	err := pl.Policy.EvaluateIdentities(identities)
	if err != nil {
		logger.Debugf("Signature set did not satisfy policy %s", pl.policyName)
	} else {
		logger.Debugf("Signature set satisfies policy %s", pl.policyName)
	}
	return err
}

func (pl *PolicyLogger) Convert() (*cb.SignaturePolicyEnvelope, error) {
	logger.Debugf("== Converting %T Policy %s ==", pl.Policy, pl.policyName)

	convertiblePolicy, ok := pl.Policy.(Converter)
	if !ok {
		logger.Errorf("policy (name='%s',type='%T') is not convertible to SignaturePolicyEnvelope", pl.policyName, pl.Policy)
		return nil, errors.Errorf("policy (name='%s',type='%T') is not convertible to SignaturePolicyEnvelope", pl.policyName, pl.Policy)
	}

	cp, err := convertiblePolicy.Convert()
	if err != nil {
		logger.Errorf("== Error Converting %T Policy %s, err %s", pl.Policy, pl.policyName, err.Error())
	} else {
		logger.Debugf("== Done Converting %T Policy %s", pl.Policy, pl.policyName)
	}

	return cp, err
}

// GetPolicy returns a policy and true if it was the policy requested, or false if it is the default reject policy
func (pm *ManagerImpl) GetPolicy(id string) (Policy, bool) {
	if id == "" {
		logger.Errorf("Returning dummy reject all policy because no policy ID supplied")
		return rejectPolicy(id), false
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Only call Convert on policies known to implement Converter (signature-type policies built from a SignaturePolicyEnvelope)
  2. Check policy existence first so rejectPolicy is never converted
  3. Implement Convert() on custom policy types if conversion must be supported

Example fix

// before
p, _ := mgr.GetPolicy("Missing")
env, err := p.(*policies.PolicyLogger).Convert() // not convertible
// after
if c, ok := p.(policies.Converter); ok {
  env, err := c.Convert()
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify the policy exists and is a signature policy before converting
if _, ok := mgr.Manager(nil); !ok { return errors.New("no manager") }
p, _ := mgr.GetPolicy(name)
_ = p

Type guard

func asConverter(p policies.Policy) (policies.Converter, bool) {
  c, ok := p.(policies.Converter)
  return c, ok
}

Try / catch

env, err := policyLogger.Convert()
if err != nil && strings.Contains(err.Error(), "is not convertible") {
  return fmt.Errorf("cannot sign against policy %s: not a signature policy", name)
}

Prevention

When it happens

Trigger: Calling Convert on a PolicyLogger whose underlying Policy is not convertible (e.g. a rejectPolicy placeholder from GetPolicy on a missing name, or a custom policy type without a Convert method).

Common situations: Attempting to pre-sign a config update using a policy that resolved to the reject sentinel; custom policy implementations that do not implement Converter; invoking conversion on implicit policies whose sub-policies are unconvertible.

Related errors


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