hyperledger/fabric · error

Invalid Proposal's SignatureHeader during check policy on ch

Error message

Invalid Proposal's SignatureHeader during check policy on channel [%s] with policy [%s]: [%s]

What it means

CheckPolicy then unmarshals header.SignatureHeader with protoutil.UnmarshalSignatureHeader to obtain the creator identity used to verify the signature. If the SignatureHeader bytes are empty or malformed, the creator cannot be recovered and the error is returned with the channel, policy, and cause.

Source

Thrown at core/policy/policy.go:93

	policyManager := p.channelPolicyManagerGetter.Manager(channelID)
	if policyManager == nil {
		return fmt.Errorf("Failed to get policy manager for channel [%s]", channelID)
	}

	// Prepare SignedData
	proposal, err := protoutil.UnmarshalProposal(signedProp.ProposalBytes)
	if err != nil {
		return fmt.Errorf("Failing extracting proposal during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err)
	}

	header, err := protoutil.UnmarshalHeader(proposal.Header)
	if err != nil {
		return fmt.Errorf("Failing extracting header during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err)
	}

	shdr, err := protoutil.UnmarshalSignatureHeader(header.SignatureHeader)
	if err != nil {
		return fmt.Errorf("Invalid Proposal's SignatureHeader during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err)
	}

	sd := []*protoutil.SignedData{{
		Data:      signedProp.ProposalBytes,
		Identity:  shdr.Creator,
		Signature: signedProp.Signature,
	}}

	return p.CheckPolicyBySignedData(channelID, policyName, sd)
}

// CheckPolicyNoChannel checks that the passed signed proposal is valid with the respect to
// passed policy on the local MSP.
func (p *policyChecker) CheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal) error {
	if policyName == "" {
		return errors.New("Invalid policy name during channelless check policy. Name must be different from nil.")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Construct the proposal via the SDK's ChaincodeHeader/SignatureHeader helpers so creator MSP identity is serialized correctly
  2. Read the wrapped underlying error to distinguish empty bytes from a type mismatch
  3. Verify the client's fabric-protos version matches the peer's
  4. Validate client identity enrollment (Creator must be a valid serialized identity from the local MSP)

Example fix

// before
shdr := &common.SignatureHeader{} // empty creator
// after
creator, _ := id.Marshal()
shdrBytes, _ := protoutil.Marshal(protoutil.NewSignatureHeader(id))
Defensive patterns

Strategy: try-catch

Validate before calling

sh, err := protoutil.UnmarshalSignatureHeader(header.SignatureHeader)
if err != nil || len(sh.Creator) == 0 { return errors.New("SignatureHeader/Creator invalid") }

Type guard

function hasCreator(sh) { return sh && sh.creator && sh.creator.length > 0; }

Try / catch

err := checker.CheckPolicy(policyName, signedProp)
if err != nil {
    if strings.Contains(err.Error(), "Invalid Proposal's SignatureHeader") {
        // creator identity unrecoverable: reject the proposal
    }
    return err
}

Prevention

When it happens

Trigger: Proposal's Header contains a SignatureHeader field that is nil/empty or bytes of a different protobuf type; a manually constructed SignatureHeader with a wrong Creator field.

Common situations: Custom signing code that sets the Creator incorrectly or leaves SignatureHeader unset; SDK/peer proto version drift; proposals relayed through middleware that drops nested fields.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/3d37af5177083fb2. Report an issue: GitHub.