{"record":{"id":"b98c25cd7189aca4","repo":"hyperledger/fabric","slug":"data-unmarshalling-error-s","errorCode":null,"errorMessage":"data unmarshalling error: %s","messagePattern":"data unmarshalling error: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/configverifier.go","lineNumber":86,"sourceCode":"\n\tif payload.Header == nil {\n\t\treturn fmt.Errorf(\"no header was set\")\n\t}\n\n\tif payload.Header.ChannelHeader == nil {\n\t\treturn fmt.Errorf(\"no channel header was set\")\n\t}\n\n\tchdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"channel header unmarshalling error: %s\", err)\n\t}\n\n\tswitch chdr.Type {\n\tcase int32(common.HeaderType_CONFIG):\n\t\tconfigEnvelope := &common.ConfigEnvelope{}\n\t\tif err = proto.Unmarshal(payload.Data, configEnvelope); err != nil {\n\t\t\treturn fmt.Errorf(\"data unmarshalling error: %s\", err)\n\t\t}\n\t\treturn cbv.verifyConfigUpdateMsg(envelope, configEnvelope, chdr)\n\tdefault:\n\t\treturn errors.Errorf(\"unexpected envelope type %s\", common.HeaderType_name[chdr.Type])\n\t}\n}\n\nfunc (cbv *ConfigBlockValidator) checkConsentersMatchPolicy(conf *common.Config) error {\n\tif conf == nil {\n\t\treturn fmt.Errorf(\"empty Config\")\n\t}\n\n\tif conf.ChannelGroup == nil {\n\t\treturn fmt.Errorf(\"empty channel group\")\n\t}\n\n\tif len(conf.ChannelGroup.Groups) == 0 {\n\t\treturn fmt.Errorf(\"no groups in channel group\")","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/configverifier.go#L68-L104","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: raw ConfigUpdate marshaled as CONFIG envelope data\npayload.Data = protoutil.MarshalOrPanic(configUpdate)\n// after\nconfigEnvelope := &common.ConfigEnvelope{Config: &common.Config{LastUpdate: configUpdate}}\npayload.Data = protoutil.MarshalOrPanic(configEnvelope)","handlingStrategy":"validation","validationCode":"if chdr.Type == int32(common.HeaderType_CONFIG) {\n    probe := &common.ConfigEnvelope{}\n    if err := proto.Unmarshal(payload.Data, probe); err != nil {\n        return fmt.Errorf(\"CONFIG payload data is not a ConfigEnvelope: %w\", err)\n    }\n    if probe.Config == nil {\n        return errors.New(\"ConfigEnvelope.Config is nil\")\n    }\n}","typeGuard":"func isConfigEnvelope(data []byte) (*common.ConfigEnvelope, bool) {\n    ce := &common.ConfigEnvelope{}\n    if err := proto.Unmarshal(data, ce); err != nil || ce.Config == nil {\n        return nil, false\n    }\n    return ce, true\n}","tryCatchPattern":"if err := cbv.ValidateConfig(envelope); err != nil {\n    if strings.Contains(err.Error(), \"data unmarshalling error\") {\n        return fmt.Errorf(\"CONFIG envelope data invalid: wrap the ConfigUpdate in common.ConfigEnvelope{Config: ...}\")\n    }\n    return err\n}","preventionTips":["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."],"tags":["hyperledger-fabric","ordering","protobuf","deserialization","config-transaction"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}