hyperledger/fabric · error
data unmarshalling error: %s
Error message
data unmarshalling error: %s
What it means
ValidateConfig in orderer/consensus/smartbft/configverifier.go:86 returns "data unmarshalling error: %s" when, for an envelope typed HeaderType_CONFIG, proto.Unmarshal of payload.Data into common.ConfigEnvelope fails. The envelope claims to be a config transaction, but its Data section is not a valid protobuf ConfigEnvelope.
Source
Thrown at orderer/consensus/smartbft/configverifier.go:86
if payload.Header == nil {
return fmt.Errorf("no header was set")
}
if payload.Header.ChannelHeader == nil {
return fmt.Errorf("no channel header was set")
}
chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
if err != nil {
return fmt.Errorf("channel header unmarshalling error: %s", err)
}
switch chdr.Type {
case int32(common.HeaderType_CONFIG):
configEnvelope := &common.ConfigEnvelope{}
if err = proto.Unmarshal(payload.Data, configEnvelope); err != nil {
return fmt.Errorf("data unmarshalling error: %s", err)
}
return cbv.verifyConfigUpdateMsg(envelope, configEnvelope, chdr)
default:
return errors.Errorf("unexpected envelope type %s", common.HeaderType_name[chdr.Type])
}
}
func (cbv *ConfigBlockValidator) checkConsentersMatchPolicy(conf *common.Config) error {
if conf == nil {
return fmt.Errorf("empty Config")
}
if conf.ChannelGroup == nil {
return fmt.Errorf("empty channel group")
}
if len(conf.ChannelGroup.Groups) == 0 {
return fmt.Errorf("no groups in channel group")View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure the CONFIG-typed envelope's Data is a marshaled common.ConfigEnvelope{Config: &common.Config{...}} (containing ChannelGroup/Config/LastUpdate), not a bare ConfigUpdate.
- Let the SDK/orderer construct the config envelope (submit a CONFIG_UPDATE envelope and let ProcessConfigUpdateMsg wrap it) rather than hand-building.
- Verify payload.Data was produced by proto.Marshal on a ConfigEnvelope, and re-marshal after any struct mutation.
- If the data came from a block, check block integrity and re-read from another orderer.
Example fix
// before: raw ConfigUpdate marshaled as CONFIG envelope data
payload.Data = protoutil.MarshalOrPanic(configUpdate)
// after
configEnvelope := &common.ConfigEnvelope{Config: &common.Config{LastUpdate: configUpdate}}
payload.Data = protoutil.MarshalOrPanic(configEnvelope) Defensive patterns
Strategy: validation
Validate before calling
if chdr.Type == int32(common.HeaderType_CONFIG) {
probe := &common.ConfigEnvelope{}
if err := proto.Unmarshal(payload.Data, probe); err != nil {
return fmt.Errorf("CONFIG payload data is not a ConfigEnvelope: %w", err)
}
if probe.Config == nil {
return errors.New("ConfigEnvelope.Config is nil")
}
} Type guard
func isConfigEnvelope(data []byte) (*common.ConfigEnvelope, bool) {
ce := &common.ConfigEnvelope{}
if err := proto.Unmarshal(data, ce); err != nil || ce.Config == nil {
return nil, false
}
return ce, true
} Try / catch
if err := cbv.ValidateConfig(envelope); err != nil {
if strings.Contains(err.Error(), "data unmarshalling error") {
return fmt.Errorf("CONFIG envelope data invalid: wrap the ConfigUpdate in common.ConfigEnvelope{Config: ...}")
}
return err
} Prevention
- For CONFIG-type envelopes, set payload.Data to a marshaled common.ConfigEnvelope, never a bare ConfigUpdate or Transaction.
- Submit config changes as CONFIG_UPDATE transactions and let the orderer construct the config envelope.
- Round-trip test (marshal then unmarshal) any hand-built config envelope before broadcasting.
- Validate ConfigEnvelope.Config != nil after decoding in client-side checks.
When it happens
Trigger: chdr.Type == HeaderType_CONFIG and proto.Unmarshal(payload.Data, configEnvelope) returns an error — payload.Data holds malformed bytes, a different message type (e.g. a Transaction or ConfigUpdate instead of ConfigEnvelope), or corrupted data.
Common situations: A client wrapping a raw ConfigUpdate in a CONFIG envelope instead of letting the orderer's ProcessConfigUpdateMsg build the ConfigEnvelope; hand-built config envelopes in tooling/tests; corrupted ledger blocks; cross-version serialization bugs in custom submission paths.
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
- channel header unmarshalling error: %s
- failed to deserialize values
- failed parsing request
- Failed unmarshalling GossipMessage from envelope: %v
- Cannot read channels list response, %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/b98c25cd7189aca4.
Report an issue: GitHub.