hyperledger/fabric · error

Invalid Proposal's SignatureHeader during channelless check

Error message

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

What it means

The Proposal and Header unmarshaled fine, but header.SignatureHeader could not be decoded into a common.SignatureHeader, which carries the creator identity and nonce. Since the channelless policy check must deserialize the creator to evaluate the local MSP principal, a broken SignatureHeader is fatal to the check.

Source

Thrown at core/policy/policy.go:128

	}

	if signedProp == nil {
		return fmt.Errorf("Invalid signed proposal during channelless check policy with policy [%s]", policyName)
	}

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

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

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

	// Deserialize proposal's creator with the local MSP
	id, err := p.localMSP.DeserializeIdentity(shdr.Creator)
	if err != nil {
		logger.Warnw("Failed deserializing proposal creator during channelless check policy", "error", err, "policyName", policyName, "identity", protoutil.LogMessageForSerializedIdentity(shdr.Creator))
		return fmt.Errorf("Failed deserializing proposal creator during channelless check policy with policy [%s]: [%s]", policyName, err)
	}

	// Load MSPPrincipal for policy
	principal, err := p.principalGetter.Get(policyName)
	if err != nil {
		return fmt.Errorf("Failed getting local MSP principal during channelless check policy with policy [%s]: [%s]", policyName, err)
	}

	// Verify that proposal's creator satisfies the principal
	err = id.SatisfiesPrincipal(principal)
	if err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Populate common.SignatureHeader (Creator = marshaled serialized identity, Nonce) and marshal it into header.SignatureHeader on the client.
  2. Before sending, round-trip unmarshal header.SignatureHeader locally to verify it is a valid SignatureHeader.
  3. Ensure Creator bytes come from msp.SerializationOfIdentity / the SDK's identity serializer, not raw certificates or PEM blobs.
  4. Check transport for truncation and confirm byte lengths match client-side marshaled sizes.

Example fix

// before
hdr := &common.Header{ChannelHeader: chBytes} // SignatureHeader missing

// after
shBytes, err := protoutil.Marshal(&common.SignatureHeader{Creator: creator, Nonce: nonce})
if err != nil { return err }
hdr := &common.Header{ChannelHeader: chBytes, SignatureHeader: shBytes}
Defensive patterns

Strategy: validation

Validate before calling

hdr, err := protoutil.UnmarshalHeader(proposal.Header)
if err != nil { return err }
if len(hdr.SignatureHeader) == 0 {
    return errors.New("header.SignatureHeader is empty")
}
if _, err := protoutil.UnmarshalSignatureHeader(hdr.SignatureHeader); err != nil {
    return fmt.Errorf("invalid SignatureHeader: %w", err)
}

Type guard

func hasValidSignatureHeader(hdr *common.Header) bool {
    if hdr == nil || len(hdr.SignatureHeader) == 0 {
        return false
    }
    _, err := protoutil.UnmarshalSignatureHeader(hdr.SignatureHeader)
    return err == nil
}

Try / catch

err := policyMgr.CheckPolicy(policyName, signedProp)
if err != nil && strings.Contains(err.Error(), "SignatureHeader") {
    // rebuild SignatureHeader with creator+nonce and re-sign
}

Prevention

When it happens

Trigger: SignedProposal whose header decodes but whose SignatureHeader field is empty/garbage — e.g. header constructed without a SignatureHeader, or bytes assigned to the wrong field of common.Header, or truncation in transit.

Common situations: Clients assembling common.Header manually and filling only ChannelHeader; signing code that clears/mutates SignatureHeader after signing; corrupted messages from a buggy gateway.

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/52093c26ec064ed3. Report an issue: GitHub.