{"record":{"id":"1c9918c76227e6af","repo":"hyperledger/fabric","slug":"policy-with-reference-s-on-channel-s-is-not","errorCode":null,"errorMessage":"policy with reference '%s' on channel '%s' is not convertible to SignaturePolicyEnvelope","messagePattern":"policy with reference '(.+?)' on channel '(.+?)' is not convertible to SignaturePolicyEnvelope","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/metadata_provider.go","lineNumber":93,"sourceCode":"func (mp *MetadataProvider) toSignaturePolicyEnvelope(channelID string, policyBytes []byte) ([]byte, error) {\n\tp := &peer.ApplicationPolicy{}\n\terr := proto.Unmarshal(policyBytes, p)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to unmarshal ApplicationPolicy bytes\")\n\t}\n\n\tswitch policy := p.Type.(type) {\n\tcase *peer.ApplicationPolicy_SignaturePolicy:\n\t\treturn protoutil.MarshalOrPanic(policy.SignaturePolicy), nil\n\tcase *peer.ApplicationPolicy_ChannelConfigPolicyReference:\n\t\tp, err := mp.ChannelPolicyReferenceProvider.NewPolicy(channelID, policy.ChannelConfigPolicyReference)\n\t\tif err != nil {\n\t\t\treturn nil, errors.WithMessagef(err, \"could not retrieve policy for reference '%s' on channel '%s'\", policy.ChannelConfigPolicyReference, channelID)\n\t\t}\n\n\t\tcp, ok := p.(policies.Converter)\n\t\tif !ok {\n\t\t\treturn nil, errors.Errorf(\"policy with reference '%s' on channel '%s' is not convertible to SignaturePolicyEnvelope\", policy.ChannelConfigPolicyReference, channelID)\n\t\t}\n\n\t\tspe, err := cp.Convert()\n\t\tif err != nil {\n\t\t\treturn nil, errors.WithMessagef(err, \"error converting policy with reference '%s' on channel '%s' to SignaturePolicyEnvelope\", policy.ChannelConfigPolicyReference, channelID)\n\t\t}\n\n\t\treturn proto.Marshal(spe)\n\tdefault:\n\t\t// this will only happen if a new policy type is added to the oneof\n\t\treturn nil, errors.Errorf(\"unsupported policy type %T on channel '%s'\", policy, channelID)\n\t}\n}\n\n// Metadata implements the metadata retriever support interface for service discovery\nfunc (mp *MetadataProvider) Metadata(channel string, ccName string, collections ...string) *chaincode.Metadata {\n\tccInfo, err := mp.ChaincodeInfoProvider.ChaincodeInfo(channel, ccName)\n\tif err != nil {","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/metadata_provider.go#L75-L111","documentation":"When the ApplicationPolicy holds a ChannelConfigPolicyReference, lifecycle resolves it to a policies.Policy and then type-asserts to policies.Converter so it can be converted to a SignaturePolicyEnvelope. Policies that are not convertible (e.g. an ImplicitMetaPolicy) fail the assertion and this error is thrown. Discovery needs a concrete signature policy but only an abstract reference was found.","triggerScenarios":"Metadata (service discovery) is asked for a chaincode whose endorsement policy is a channel-config reference to a policy type lacking a Convert() implementation, such as an implicit-meta policy.","commonSituations":"Setting endorsement policy to '/Channel/Application/Endorsement' (implicit meta) where discovery requires a signature policy; using Any/Majority implicit policies as endorsement policy references; legacy discovery clients expecting envelope-form policies.","solutions":["Set the chaincode endorsement policy to an explicit signature policy (e.g. -E \"AND('Org1.peer','Org2.peer')\") instead of an implicit-meta channel reference","Define a signature-policy in channel config and reference that instead of the implicit-meta one","If implicit meta semantics are needed, use discovery's layout computation with a convertible policy","Document that discovery of this chaincode requires a SignaturePolicyEnvelope-representable policy"],"exampleFix":"// before: implicit-meta reference\n-E /Channel/Application/Endorsement\n// error: not convertible to SignaturePolicyEnvelope\n// after: explicit signature policy\npeer lifecycle chaincode approveformyorg -C mychannel --name mycc --sequence 1 -E \"AND('Org1MSP.peer','Org2MSP.peer')\"","handlingStrategy":"validation","validationCode":"# Before setting an endorsement policy reference, ensure it is a signature policy,\n# not an implicit-meta policy:\njq '.channel_group.groups.Application.policies[\"MyPolicy\"].policy.type' config.json\n# 1 = SignaturePolicy (ok), 3 = ImplicitMeta (will hit 'not convertible')","typeGuard":null,"tryCatchPattern":"envBytes, err := mp.toSignaturePolicyEnvelope(channelID, policyBytes)\nif err != nil {\n  if strings.Contains(err.Error(), \"not convertible to SignaturePolicyEnvelope\") {\n    // request an explicit signature policy instead of the channel reference\n  }\n}","preventionTips":["Use AND/OR signature policies for endorsement when discovery metadata is needed","Avoid referencing implicit-meta policies as endorsement policies","Document policy types in channel config","Test discovery output after approval"],"tags":["fabric","policy","discovery","signature-policy","implicit-meta"],"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"}