{"record":{"id":"bf37093aa2c44331","repo":"hyperledger/fabric","slug":"no-signed-data-during-channelless-check-policy-wit","errorCode":null,"errorMessage":"no signed data during channelless check policy with policy [%s]","messagePattern":"no signed data during channelless check policy with policy \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/policy/policy.go","lineNumber":197,"sourceCode":"\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\n\t\tid, err := p.localMSP.DeserializeIdentity(data.Identity)\n\t\tif err != nil {\n\t\t\tlogger.Warnw(\"Failed deserializing signed data identity during channelless check policy\", \"error\", err, \"policyName\", policyName, \"identity\", protoutil.LogMessageForSerializedIdentity(data.Identity))\n\t\t\treturn fmt.Errorf(\"failed deserializing signed data identity during channelless check policy with policy [%s]: [%s]\", policyName, err)\n\t\t}\n\n\t\t// Load MSPPrincipal for policy\n\t\tprincipal, err := p.principalGetter.Get(policyName)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed getting local MSP principal during channelless check policy with policy [%s]: [%s]\", policyName, err)\n\t\t}\n\n\t\t// Verify that proposal's creator satisfies the principal\n\t\terr = id.SatisfiesPrincipal(principal)","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/policy/policy.go#L179-L215","documentation":"CheckPolicyNoChannelBySignedData requires at least one SignedData entry because each entry's identity is checked against the local MSP principal and its signature verified. An empty (or nil) slice means there is nothing to authorize, so the call fails immediately with this validation error before any MSP work.","triggerScenarios":"Calling CheckPolicyNoChannelBySignedData(policyName, nil) or with an empty slice (len(signedData) == 0); commonly when the caller built signed data conditionally and the condition never produced entries, or unmarshalling produced zero entries.","commonSituations":"Batch code that collects signatures into a slice which ends up empty when all signers fail earlier; tests passing an empty fixture; loops over proposals that were all filtered out, then calling the checker unconditionally with the accumulated (empty) slice.","solutions":["Ensure at least one SignedData entry with Data, Identity, and Signature populated before calling.","Guard the call: if len(signedData) == 0 { return errors.New(\"no signed data\") }.","Trace why the slice is empty — usually an upstream signing or unmarshalling step failed silently and must be surfaced.","If checking a single proposal, use CheckPolicyNoChannel, which builds its own SignedData from the proposal."],"exampleFix":"// before\nvar sd []*protoutil.SignedData // never populated\nerr := policyChecker.CheckPolicyNoChannelBySignedData(\"Admins\", sd)\n// after\nif len(sd) == 0 {\n    return errors.New(\"cannot check policy: no signed data collected\")\n}\nerr := policyChecker.CheckPolicyNoChannelBySignedData(\"Admins\", sd)","handlingStrategy":"validation","validationCode":"if len(signedData) == 0 {\n    return errors.New(\"at least one SignedData entry is required for a channelless policy check\")\n}\nerr := policyChecker.CheckPolicyNoChannelBySignedData(policyName, signedData)","typeGuard":"func nonEmptySignedData(sd []*protoutil.SignedData) bool { return len(sd) > 0 }","tryCatchPattern":null,"preventionTips":["Only call the checker after at least one signer has been collected and verified structurally.","Surface upstream signing failures instead of silently producing an empty slice.","For single-proposal checks prefer CheckPolicyNoChannel, which constructs its own SignedData.","Log slice length before the call when debugging authorization flows."],"tags":["hyperledger-fabric","input-validation","empty-collection","signed-data"],"backgroundTag":"empty-input","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"}