hyperledger/fabric · error
invalid type %s, expected %s
Error message
invalid type %s, expected %s
What it means
UnmarshalEnvelopeOfType unmarshals an envelope payload into a message and verifies the envelope's channel header type matches the expected header type. This error is thrown when the envelope's decoded header type (e.g. HEADER_TYPE_ENDORSER_TRANSACTION) does not match the headerType argument the caller requested. It is a type-mismatch guard, not a corruption error: the envelope parsed fine, it just isn't the kind of message the caller expected.
Source
Thrown at protoutil/commonutils.go:75
// UnmarshalEnvelopeOfType unmarshals an envelope of the specified type,
// including unmarshalling the payload data
func UnmarshalEnvelopeOfType(envelope *cb.Envelope, headerType cb.HeaderType, message proto.Message) (*cb.ChannelHeader, error) {
payload, err := UnmarshalPayload(envelope.Payload)
if err != nil {
return nil, err
}
if payload.Header == nil {
return nil, errors.New("envelope must have a Header")
}
chdr, err := UnmarshalChannelHeader(payload.Header.ChannelHeader)
if err != nil {
return nil, err
}
if chdr.Type != int32(headerType) {
return nil, errors.Errorf("invalid type %s, expected %s", cb.HeaderType(chdr.Type), headerType)
}
err = proto.Unmarshal(payload.Data, message)
err = errors.Wrapf(err, "error unmarshalling message for type %s", headerType)
return chdr, err
}
// ExtractEnvelopeOrPanic retrieves the requested envelope from a given block
// and unmarshals it -- it panics if either of these operations fail
func ExtractEnvelopeOrPanic(block *cb.Block, index int) *cb.Envelope {
envelope, err := ExtractEnvelope(block, index)
if err != nil {
panic(err)
}
return envelope
}
// ExtractEnvelope retrieves the requested envelope from a given block andView on GitHub (pinned to 2736b63f8f)
Solutions
- Check the actual header type of your envelope: unmarshal the payload and inspect chdr.Type, then route it to the matching decoder instead of the expected one.
- Verify you are passing the correct cb.HeaderType constant to UnmarshalEnvelopeOfType for the data you actually have.
- If the envelope should be of the expected type, trace its producer (transaction proposal or config update) — the submitting component built the wrong payload type.
- For genesis/config blocks, ensure the block you feed to channelConfigFromBlock/extractChannelConfig is a config block (IsConfigBlock) not an ordinary block with transactions.
Example fix
// before
envelope, _ := ExtractEnvelope(block, 0)
var config cb.ConfigEnvelope
err := protoutil.UnmarshalEnvelopeOfType(envelope, cb.HeaderType_CONFIG, &config) // fails: envelope is a transaction
// after
chdr, _ := protoutil.ChannelHeader(envelope)
if cb.HeaderType(chdr.Type) == cb.HeaderType_CONFIG {
err = protoutil.UnmarshalEnvelopeOfType(envelope, cb.HeaderType_CONFIG, &config)
} else {
err = protoutil.UnmarshalEnvelopeOfType(envelope, cb.HeaderType_ENDORSER_TRANSACTION, &tx)
} Defensive patterns
Strategy: validation
Validate before calling
func hasHeaderType(t *testing.T, env *cb.Envelope, want cb.HeaderType) bool {
chdr, err := protoutil.ChannelHeader(env)
if err != nil {
return false
}
return cb.HeaderType(chdr.Type) == want
}
// call protoutil.UnmarshalEnvelopeOfType(env, want, msg) only when hasHeaderType(env, want) Type guard
func envelopeHasType(env *cb.Envelope, want cb.HeaderType) bool {
chdr, err := protoutil.ChannelHeader(env)
return err == nil && cb.HeaderType(chdr.Type) == want
} Try / catch
var msg cb.ConfigEnvelope
if err := protoutil.UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, &msg); err != nil {
// inspect actual type and route accordingly
chdr, herr := protoutil.ChannelHeader(env)
if herr == nil {
return fmt.Errorf("expected CONFIG, got %s: %w", cb.HeaderType(chdr.Type), err)
}
return err
} Prevention
- Inspect chdr.Type and branch on it before choosing a decoder type
- Use IsConfigBlock/HasConfigTx to confirm a block is a config block before config decoding
- Keep fabric-protos versions consistent across producing and consuming components
- Unit-test envelope construction paths so header type always matches payload message
When it happens
Trigger: Calling UnmarshalEnvelopeOfType with a specific cb.HeaderType (e.g. cb.HeaderType_CONFIG) against an envelope whose ChannelHeader.Type differs — e.g. passing an orderer config block to a function expecting a transaction, or feeding an ENDORSER_TRANSACTION envelope into a CONFIG decoder.
Common situations: Delivering blocks/transactions to the wrong processing path; peer/orderer code validating that a block actually contains a config transaction before applying it (ProcessConfigMsg, validateConfigBlock); fabric-sdk or external tooling submitting a payload of the wrong type for a channel; config updates sent as normal transactions.
Related errors
- malformed org definition for org: %s
- error encode input
- message of type %s unknown
- error marshaling: proto: Marshal called with nil
- error marshaling
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/7e2d3d54e42907a8.
Report an issue: GitHub.