{"record":{"id":"8306a5f3757cfa6b","repo":"hyperledger/fabric","slug":"failing-extracting-proposal-during-channelless-che","errorCode":null,"errorMessage":"Failing extracting proposal during channelless check policy with policy [%s]: [%s]","messagePattern":"Failing extracting proposal during channelless check policy with policy \\[(.+?)\\]: \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/policy/policy.go","lineNumber":118,"sourceCode":"\t}}\n\n\treturn p.CheckPolicyBySignedData(channelID, policyName, sd)\n}\n\n// CheckPolicyNoChannel checks that the passed signed proposal is valid with the respect to\n// passed policy on the local MSP.\nfunc (p *policyChecker) CheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal) 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 signedProp == nil {\n\t\treturn fmt.Errorf(\"Invalid signed proposal during channelless check policy with policy [%s]\", policyName)\n\t}\n\n\tproposal, err := protoutil.UnmarshalProposal(signedProp.ProposalBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Failing extracting proposal during channelless check policy with policy [%s]: [%s]\", policyName, err)\n\t}\n\n\theader, err := protoutil.UnmarshalHeader(proposal.Header)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Failing extracting header during channelless check policy with policy [%s]: [%s]\", policyName, err)\n\t}\n\n\tshdr, err := protoutil.UnmarshalSignatureHeader(header.SignatureHeader)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Invalid Proposal's SignatureHeader during channelless check policy with policy [%s]: [%s]\", policyName, err)\n\t}\n\n\t// Deserialize proposal's creator with the local MSP\n\tid, err := p.localMSP.DeserializeIdentity(shdr.Creator)\n\tif err != nil {\n\t\tlogger.Warnw(\"Failed deserializing proposal creator during channelless check policy\", \"error\", err, \"policyName\", policyName, \"identity\", protoutil.LogMessageForSerializedIdentity(shdr.Creator))\n\t\treturn fmt.Errorf(\"Failed deserializing proposal creator during channelless check policy with policy [%s]: [%s]\", policyName, err)\n\t}","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/policy/policy.go#L100-L136","documentation":"This error is thrown by CheckPolicyNoChannel in Hyperledger Fabric's peer when the bytes of a signed proposal cannot be unmarshaled into a Proposal protobuf. The channelless (system-chaincode style) policy check verifies proposal signatures without a channel context, and the first step is extracting the Proposal from SignedProp.ProposalBytes. If those bytes are corrupt, truncated, or not a serialized Proposal, protoutil.UnmarshalProposal fails and this error is returned with the underlying parse error embedded.","triggerScenarios":"Calling peer/policy CheckPolicy (or CheckPolicyNoChannel) with a SignedProp whose ProposalBytes are not a valid protobuf-encoded common.Proposal — e.g. bytes from a different message type, empty/nil payload after transport corruption, or a hand-crafted proposal built with mismatched proto schemas.","commonSituations":"Custom clients (Fabric SDK or raw gRPC) constructing SignedProposal manually with wrong proto serialization; intermediate proxies truncating or re-encoding gRPC frames; version skew where client proto definitions differ from the peer's protos.","solutions":["Verify the client builds the SignedProposal with the correct protos: ProposalBytes must marshal common.Proposal (Header + Payload), not the SignedProposal itself or other message types.","Re-generate or re-sync proto files with the Fabric version the peer runs so both sides serialize identically.","Log/inspect the raw ProposalBytes length and hex on the client side to confirm non-empty, intact bytes reach the peer.","Check for intermediaries (proxies, gateways) that might mangle the request body before it reaches the peer."],"exampleFix":"// before: stuffing the wrong message into ProposalBytes\nsp := &common.SignedProposal{ProposalBytes: signedProposalBytes}\n\n// after: marshal the Proposal correctly\npropBytes, err := protoutil.Marshal(proposal)\nif err != nil { return err }\nsp := &common.SignedProposal{ProposalBytes: propBytes, Signature: sig}","handlingStrategy":"validation","validationCode":"if signedProp == nil || len(signedProp.ProposalBytes) == 0 {\n    return errors.New(\"signed proposal has empty ProposalBytes\")\n}\nif _, err := protoutil.UnmarshalProposal(signedProp.ProposalBytes); err != nil {\n    return fmt.Errorf(\"ProposalBytes are not a valid Proposal: %w\", err)\n}","typeGuard":"func isValidSignedProposal(sp *peer.SignedProposal) bool {\n    if sp == nil || len(sp.ProposalBytes) == 0 || len(sp.Signature) == 0 {\n        return false\n    }\n    _, err := protoutil.UnmarshalProposal(sp.ProposalBytes)\n    return err == nil\n}","tryCatchPattern":"err := policyMgr.CheckPolicy(policyName, signedProp)\nvar perr *invalidProposalError\nif errors.As(err, &perr) { /* rebuild/reserialize proposal on client */ }","preventionTips":["Always marshal ProposalBytes with protoutil.Marshal of a common.Proposal","Round-trip unmarshal proposals client-side before sending","Keep proto definitions in sync with the peer's Fabric version","Log byte lengths of outgoing proposals for early corruption detection"],"tags":["hyperledger-fabric","protobuf","proposal-validation"],"backgroundTag":"protobuf-unmarshal-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"}