hyperledger/fabric · error

error unmarshalling ChaincodeHeaderExtension

Error message

error unmarshalling ChaincodeHeaderExtension

What it means

getChaincodeHeaderExtension failed to proto-unmarshal the payload header's Extension bytes into a peer.ChaincodeHeaderExtension. This means the ChaincodeHeaderExtension field of the transaction's header (chdr.Extension) is corrupt, truncated, or not a valid serialized ChaincodeHeaderExtension. The peer wraps the underlying unmarshal error with this message and VSCCValidateTx aborts validation of the transaction.

Solutions

  1. Inspect the offending transaction's payload header extension bytes and verify they serialize a peer.ChaincodeHeaderExtension (use protoc --decode_raw).
  2. Fix the client SDK / transaction-construction code so it marshals ChaincodeHeaderExtension correctly into the header extension field.
  3. If the transaction is corrupt, remove it and resubmit; a corrupted block on disk may require refetching the block from the orderer.
  4. Confirm protobuf runtime versions on the client match the Fabric proto definitions being used.

Example fix

// before: hand-built header extension bytes
hdr.Extension = someArbitraryBytes
// after
hdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: &peer.ChaincodeID{Name: ccName}}
raw, _ := proto.Marshal(hdrExt)
hdr.Extension = raw
Defensive patterns

Strategy: validation

Validate before calling

if len(envelope.Payload) == 0 || len(payload.Header.Extension) == 0 {
    return errors.New("transaction header extension missing; cannot validate")
}
ext := &peer.ChaincodeHeaderExtension{}
if err := proto.Unmarshal(payload.Header.Extension, ext); err != nil {
    return fmt.Errorf("malformed ChaincodeHeaderExtension: %w", err)
}

Type guard

func isValidHeaderExtension(b []byte) bool {
	ext := &peer.ChaincodeHeaderExtension{}
	return proto.Unmarshal(b, ext) == nil && ext.ChaincodeId != nil
}

Try / catch

result, err := v.getChaincodeHeaderExtension(chdr)
if err != nil {
    logger.Warnf("skipping tx: %v", err)
    return peer.TxValidationCode_BAD_PAYLOAD, nil
}

Prevention

When it happens

Trigger: A transaction envelope whose payload header's Extension field contains bytes that do not decode as a ChaincodeHeaderExtension protobuf (e.g. empty/corrupt extension, wrong message type serialized there, or bits flipped in transit/storage). Raised inside getChaincodeHeaderExtension, called from VSCCValidateTx during block validation.

Common situations: Malformed or tampered transactions submitted by a misbehaving client or SDK; transactions built by hand-crafted protobuf code that puts the wrong message in the header extension; corrupted blocks read from storage or received from an orderer.

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/4ee51889747e7ea7. Report an issue: GitHub.

Appendix: source

Thrown at core/committer/txvalidator/v14/vscc_validator.go:50

// newVSCCValidator creates new vscc validator
func newVSCCValidator(channelID string, cr ChannelResources, pluginValidator *PluginValidator) *VsccValidatorImpl {
	return &VsccValidatorImpl{
		channelID:       channelID,
		cr:              cr,
		pluginValidator: pluginValidator,
	}
}

func getChaincodeHeaderExtension(hdr *common.Header) (*peer.ChaincodeHeaderExtension, error) {
	chdr, err := protoutil.UnmarshalChannelHeader(hdr.ChannelHeader)
	if err != nil {
		return nil, err
	}

	chaincodeHdrExt := &peer.ChaincodeHeaderExtension{}
	err = proto.Unmarshal(chdr.Extension, chaincodeHdrExt)
	return chaincodeHdrExt, errors.Wrap(err, "error unmarshalling ChaincodeHeaderExtension")
}

// VSCCValidateTx executes vscc validation for transaction
func (v *VsccValidatorImpl) VSCCValidateTx(seq int, payload *common.Payload, envBytes []byte, block *common.Block) (peer.TxValidationCode, error) {
	chainID := v.channelID
	logger.Debugf("[%s] VSCCValidateTx starts for bytes %p", chainID, envBytes)

	// get header extensions so we have the chaincode ID
	hdrExt, err := getChaincodeHeaderExtension(payload.Header)
	if err != nil {
		return peer.TxValidationCode_BAD_HEADER_EXTENSION, err
	}

	// get channel header
	chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
	if err != nil {
		return peer.TxValidationCode_BAD_CHANNEL_HEADER, err
	}

View on GitHub (pinned to 2736b63f8f)