{"record":{"id":"96c6c880e3f863ec","repo":"hyperledger/fabric","slug":"failed-evaluating-policy-on-signed-data-during-che-96c6c8","errorCode":null,"errorMessage":"Failed evaluating policy on signed data during check policy on channel [%s] with policy [%s]: [%s]","messagePattern":"Failed evaluating policy on signed data during check policy on channel \\[(.+?)\\] with policy \\[(.+?)\\]: \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/policy/policy.go","lineNumber":183,"sourceCode":"\n\tif sd == nil {\n\t\treturn fmt.Errorf(\"Invalid signed data during check policy on channel [%s] with policy [%s]\", channelID, policyName)\n\t}\n\n\t// Get Policy\n\tpolicyManager := p.channelPolicyManagerGetter.Manager(channelID)\n\tif policyManager == nil {\n\t\treturn fmt.Errorf(\"Failed to get policy manager for channel [%s]\", channelID)\n\t}\n\n\t// Recall that get policy always returns a policy object\n\tpolicy, _ := policyManager.GetPolicy(policyName)\n\n\t// Evaluate the policy\n\terr := policy.EvaluateSignedData(sd)\n\tif err != nil {\n\t\tlogger.Warnw(\"Failed evaluating policy on signed data\", \"error\", err, \"policyName\", policyName, \"identities\", protoutil.LogMessageForSerializedIdentities(sd))\n\t\treturn fmt.Errorf(\"Failed evaluating policy on signed data during check policy on channel [%s] with policy [%s]: [%s]\", channelID, policyName, err)\n\t}\n\n\treturn nil\n}\n\n// CheckPolicyNoChannelBySignedData checks that the passed signed data are valid with the respect to\n// passed policy on the local MSP.\nfunc (p *policyChecker) CheckPolicyNoChannelBySignedData(policyName string, signedData []*protoutil.SignedData) error {\n\tif policyName == \"\" {\n\t\treturn errors.New(\"invalid policy name during channelless check policy. Name must be different from nil.\")\n\t}\n\n\tif len(signedData) == 0 {\n\t\treturn fmt.Errorf(\"no signed data during channelless check policy with policy [%s]\", policyName)\n\t}\n\n\tfor _, data := range signedData {\n\t\t// Deserialize identity with the local MSP","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/policy/policy.go#L165-L201","documentation":"This error is returned by CheckPolicyBySignedData when the channel policy retrieved for policyName fails to evaluate against the supplied SignedData. It is a wrapper: the real cause (signature verification failure, identity not satisfying the policy principals, missing signatures, etc.) is embedded in the [%s] suffix from policy.EvaluateSignedData. The policy object itself was found (GetPolicy never returns a usable error here), so this failure is purely about evaluation, not policy lookup.","triggerScenarios":"Calling CheckPolicy (or CheckPolicyBySignedData directly, e.g. in tests like TestCheckPolicyBySignedDataInvalidArgs) with valid channelID/policyName/non-nil sd, but the sd identities do not satisfy the channel policy (e.g. Writers/Readers), signatures are invalid or stale, or the signed data was built from an envelope signed by a cert not in the channel MSP.","commonSituations":"Endorsement/transaction validation where the submitter's cert was rotated or removed from the channel config; a proposal signed with a different key than the creator identity; testing with fabricated SignedData whose signature doesn't match; invoking a system chaincode policy (e.g. '又能Writers') with data from a peer whose MSP config is out of date.","solutions":["Read the wrapped inner error after the last ': [' to identify the real cause (signature mismatch vs principal not satisfied).","Verify the signature in sd was produced over sd.Data by the private key corresponding to sd.Identity.","Confirm sd.Identity deserializes in the channel's MSP and the identity's role satisfies the named policy (e.g. member of an org listed in Writers).","Check the peer has the latest channel config/MSP certs; re-fetch channel config and retry with freshly signed data.","If constructing SignedData manually in tests, sign protoutil.NewSignatureHeader-based bytes with the actual creator's signing identity via signingIdentity.Sign(data)."],"exampleFix":"// before: signature over wrong bytes\nsd := &protoutil.SignedData{Data: proposalBytes, Identity: creator, Signature: sigOverSomethingElse}\nerr := pc.CheckPolicyBySignedData(channelID, \"Writers\", []*protoutil.SignedData{sd})\n// after: sign the exact data with the creator's signing identity\nsig, err := signingIdentity.Sign(proposalBytes)\nif err != nil { return err }\nsd := &protoutil.SignedData{Data: proposalBytes, Identity: creator, Signature: sig}\nerr = pc.CheckPolicyBySignedData(channelID, \"Writers\", []*protoutil.SignedData{sd})","handlingStrategy":"try-catch","validationCode":"// Go: validate inputs and confirm identities/signatures before calling\nif channelID == \"\" || policyName == \"\" || sd == nil { return errors.New(\"invalid arguments to CheckPolicyBySignedData\") }\nfor _, d := range sd {\n    if _, err := mspManager.DeserializeIdentity(d.Identity); err != nil {\n        return fmt.Errorf(\"identity not in channel MSP: %w\", err)\n    }\n}","typeGuard":"func validSignedData(sd []*protoutil.SignedData) bool {\n    if len(sd) == 0 { return false }\n    for _, d := range sd {\n        if d == nil || len(d.Data) == 0 || len(d.Identity) == 0 || len(d.Signature) == 0 { return false }\n    }\n    return true\n}","tryCatchPattern":"if err := policyChecker.CheckPolicyBySignedData(channelID, policyName, sd); err != nil {\n    var policyErr error\n    if strings.Contains(err.Error(), \"Failed evaluating policy on signed data\") {\n        // log full error: the wrapped cause after ': [' carries the real reason\n        logger.Errorf(\"policy evaluation rejected signed data: %v\", err)\n        policyErr = fmt.Errorf(\"submitter does not satisfy policy %s on channel %s\", policyName, channelID)\n    }\n    return policyErr\n}","preventionTips":["Always sign exactly the bytes placed in SignedData.Data with the identity's own signing key.","Keep peer channel config and MSP certs up to date with cert rotations.","Log the wrapped inner error, not just the wrapper, when diagnosing.","In tests, build SignedData via the real signing identity (Sign), never with fabricated signatures.","Verify the named policy exists on the channel (GetPolicy via the manager) before submitting."],"tags":["hyperledger-fabric","policy-evaluation","signature-verification","msp"],"backgroundTag":"policy-evaluation-failed","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"}