{"record":{"id":"2d70e255dc6a069e","repo":"hyperledger/fabric","slug":"subpolicy-number-d-type-t-of-policy-s-is-not-co","errorCode":null,"errorMessage":"subpolicy number %d type %T of policy %s is not convertible","messagePattern":"subpolicy number (.+?) type %T of policy (.+?) is not convertible","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/policies/convert.go","lineNumber":117,"sourceCode":"\tconverted := &cb.SignaturePolicyEnvelope{\n\t\tVersion: 0,\n\t\tRule: &cb.SignaturePolicy{\n\t\t\tType: &cb.SignaturePolicy_NOutOf_{\n\t\t\t\tNOutOf: &cb.SignaturePolicy_NOutOf{\n\t\t\t\t\tN: int32(p.Threshold),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\t// the conversion approach for an implicit meta\n\t// policy is to convert each of the subpolicies,\n\t// merge it with the previous one and return the\n\t// merged policy\n\tfor i, subPolicy := range p.SubPolicies {\n\t\tconvertibleSubpolicy, ok := subPolicy.(Converter)\n\t\tif !ok {\n\t\t\treturn nil, errors.Errorf(\"subpolicy number %d type %T of policy %s is not convertible\", i, subPolicy, p.SubPolicyName)\n\t\t}\n\n\t\tspe, err := convertibleSubpolicy.Convert()\n\t\tif err != nil {\n\t\t\treturn nil, errors.WithMessagef(err, \"failed to convert subpolicy number %d of policy %s\", i, p.SubPolicyName)\n\t\t}\n\n\t\tmerge(converted, spe)\n\t}\n\n\treturn converted, nil\n}\n","sourceCodeStart":99,"sourceCodeEnd":130,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/policies/convert.go#L99-L130","documentation":"ImplicitMetaPolicy.Convert walks its subpolicies and requires each one to implement the Converter interface. If a subpolicy is of a type that cannot be converted (e.g. a raw SignaturePolicy or an unimplemented policy type), conversion aborts with this error naming the index, dynamic type, and policy name.","triggerScenarios":"Calling Convert() on an ImplicitMetaPolicy whose config proto contains subpolicies that are not convertible — e.g. a channel config policy built with a SignaturePolicyEnvelope instead of another ImplicitMetaPolicy, or an unknown policy type injected via malformed channel creation/update config.","commonSituations":"Mis-authored configtx.yaml where a nested policy is a signature policy rather than an implicit meta policy; malformed channel update transactions; proto payloads deserialized into unexpected types; tests like TestImplicitMetaPolicy_Convert* exercising bad subpolicy types.","solutions":["Fix the channel configuration so each subpolicy of the implicit meta policy is itself an ImplicitMetaPolicy (convertible)","Inspect the %T in the error to identify the offending subpolicy type and correct its configtx entry","Validate the channel config (configtxgen / configtxlator) before submitting the update","If receiving this from a peer, reject/fix the offending channel creation or update transaction"],"exampleFix":"# before (configtx.yaml)\nPolicy: OR(\"Admins\")          # becomes a signature policy subpolicy\n# after\nPolicies:\n  Readers:\n    Type: ImplicitMeta\n    Rule: \"ANY Readers\"        # nested implicit-meta subpolicies only","handlingStrategy":"validation","validationCode":"func subPoliciesConvertible(cfg *cb.ConfigGroup) error {\n\tfor name, p := range cfg.Policies {\n\t\timp := &cb.ImplicitMetaPolicy{}\n\t\tif err := proto.Unmarshal(p.Policy.Value, imp); err == nil {\n\t\t\tfor _, sp := range imp.SubPolicies {\n\t\t\t\tif _, ok := sp.(policies.Converter); !ok {\n\t\t\t\t\treturn fmt.Errorf(\"subpolicy %s of %s is not convertible (%T)\", name, name, sp)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":"func isConvertibleSubpolicy(sp interface{}) bool {\n\t_, ok := sp.(policies.Converter)\n\treturn ok\n}","tryCatchPattern":"converted, err := impPolicy.Convert()\nif err != nil {\n\tif strings.Contains(err.Error(), \"is not convertible\") {\n\t\tlog.Errorf(\"fix channel config: %v\", err) // correct the offending subpolicy type in configtx\n\t}\n\treturn err\n}","preventionTips":["Author nested policies in configtx.yaml only as ImplicitMeta rules","Run configtxgen/configtxlator validation before submitting channel updates","Check the %T in the error to identify the offending subpolicy type","Reject malformed channel creation/update transactions at submission time"],"tags":["policies","configuration","channel-config","fabric"],"backgroundTag":"policy-not-convertible","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}