{"record":{"id":"eb793b7edd102f96","repo":"hyperledger/fabric","slug":"invalid-signed-data-during-check-policy-on-channel","errorCode":null,"errorMessage":"Invalid signed data during check policy on channel [%s] with policy [%s]","messagePattern":"Invalid signed data during check policy on channel \\[(.+?)\\] with policy \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/policy/policy.go","lineNumber":167,"sourceCode":"\t}\n\n\t// Verify the signature\n\treturn id.Verify(signedProp.ProposalBytes, signedProp.Signature)\n}\n\n// CheckPolicyBySignedData checks that the passed signed data is valid with the respect to\n// passed policy on the passed channel.\nfunc (p *policyChecker) CheckPolicyBySignedData(channelID, policyName string, sd []*protoutil.SignedData) error {\n\tif channelID == \"\" {\n\t\treturn errors.New(\"Invalid channel ID name during check policy on signed data. Name must be different from nil.\")\n\t}\n\n\tif policyName == \"\" {\n\t\treturn fmt.Errorf(\"Invalid policy name during check policy on signed data on channel [%s]. Name must be different from nil.\", channelID)\n\t}\n\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","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/policy/policy.go#L149-L185","documentation":"Returned by CheckPolicyBySignedData when the sd (SignedData slice) parameter is nil. Signed data pairs identities with message bytes and signatures; without it there is nothing to evaluate against the policy, so the call is rejected before contacting the policy manager.","triggerScenarios":"Calling CheckPolicyBySignedData(channelID, policyName, nil), or via CheckPolicy when the proposal bytes/signature could not be assembled into SignedData (nil signature or proposal bytes upstream).","commonSituations":"A caller passes a partially constructed proposal where signature or proposal bytes are missing; a test harness forgets to populate SignedData; an SDK serialization step silently produced nil payloads.","solutions":["Ensure the proposal is fully created and signed: verify proposal bytes and signature are non-empty before calling.","Build the []*protoutil.SignedData correctly (identity, proposal bytes, signature) rather than passing nil.","Trace upstream serialization/signing code for silent nil returns and add explicit checks there."],"exampleFix":"// before\nerr := checker.CheckPolicyBySignedData(\"mychannel\", \"CHANNEL_READERS\", nil)\n// after\nsd := []*protoutil.SignedData{{Identity: creator, Data: proposalBytes, Signature: signature}}\nif sd == nil { return errors.New(\"signed data is required\") }\nerr := checker.CheckPolicyBySignedData(\"mychannel\", \"CHANNEL_READERS\", sd)","handlingStrategy":"validation","validationCode":"if sd == nil || len(sd) == 0 {\n    return errors.New(\"signed data must contain at least one SignedData entry with identity, data, and signature\")\n}\nfor _, d := range sd {\n    if d.Signature == nil || len(d.Data) == 0 { return errors.New(\"incomplete SignedData entry\") }\n}","typeGuard":"func isCompleteSignedData(sd []*protoutil.SignedData) bool {\n    if len(sd) == 0 { return false }\n    for _, d := range sd {\n        if len(d.Identity) == 0 || len(d.Data) == 0 || len(d.Signature) == 0 { return false }\n    }\n    return true\n}","tryCatchPattern":null,"preventionTips":["Always construct SignedData from a fully signed proposal (signature != nil, proposal bytes != nil).","Check signing errors before assembling policy-check inputs; never swallow signer errors.","Add unit tests that pass through the complete proposal-signing pipeline."],"tags":["fabric","validation","signed-data","argument-error"],"backgroundTag":"empty-required-argument","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"}