{"record":{"id":"ac5cfda344b8905e","repo":"hyperledger/fabric","slug":"no-channel-header-was-set","errorCode":null,"errorMessage":"no channel header was set","messagePattern":"no channel header was set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/configverifier.go","lineNumber":74,"sourceCode":"\tConfigUpdateProposer ConfigUpdateProposer\n\tValidatingChannel    string\n\tFilters              Filters\n\tLogger               *flogging.FabricLogger\n}\n\n// ValidateConfig validates config from envelope\nfunc (cbv *ConfigBlockValidator) ValidateConfig(envelope *common.Envelope) error {\n\tpayload, err := protoutil.UnmarshalPayload(envelope.Payload)\n\tif err != nil {\n\t\treturn err\n\t}\n\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}","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/configverifier.go#L56-L92","documentation":"ValidateConfig in orderer/consensus/smartbft/configverifier.go:74 returns \"no channel header was set\" when payload.Header exists but its ChannelHeader field is nil. The channel header carries the channel ID and envelope type; without it the validator cannot determine whether this is a CONFIG envelope or which channel it targets. This is the second of the three structural checks on the payload header.","triggerScenarios":"An envelope's payload has a Header populated with (at most) a SignatureHeader but ChannelHeader == nil, reaching ValidateConfig — typically from a malformed config envelope submitted to the SmartBFT ordering node.","commonSituations":"Tools or tests constructing common.Header with only SignatureHeader set; a serialization bug dropping the ChannelHeader bytes; corrupted ledger data; custom broadcast clients that forget to set ChannelHeader for CONFIG transactions.","solutions":["Populate common.Header.ChannelHeader with a marshaled ChannelHeader (Type=HeaderType_CONFIG, ChannelId, TxId) before submitting.","Prefer protoutil.CreateSignedEnvelope which always sets the channel header.","Check the block/transaction source for corruption and re-obtain from a trusted peer/orderer.","Add client-side validation that header.ChannelHeader != nil before broadcasting the envelope."],"exampleFix":"// before\nhdr := &common.Header{SignatureHeader: sighdrBytes}\n// after\nhdr := &common.Header{\n    ChannelHeader:   protoutil.MarshalOrPanic(&common.ChannelHeader{Type: int32(common.HeaderType_CONFIG), ChannelId: \"mychannel\"}),\n    SignatureHeader: sighdrBytes,\n}","handlingStrategy":"type-guard","validationCode":"if payload.Header == nil || payload.Header.ChannelHeader == nil {\n    return errors.New(\"envelope missing channel header; cannot submit config transaction\")\n}","typeGuard":"func hasChannelHeader(h *common.Header) bool {\n    return h != nil && h.ChannelHeader != nil\n}","tryCatchPattern":"if err := cbv.ValidateConfig(envelope); err != nil {\n    if strings.Contains(err.Error(), \"no channel header was set\") {\n        return fmt.Errorf(\"payload header lacks ChannelHeader: regenerate envelope\")\n    }\n    return err\n}","preventionTips":["Set both ChannelHeader (type, channel ID) and SignatureHeader on every common.Header.","Use protoutil.CreateSignedEnvelope rather than assembling Header fields piecemeal.","Add a pre-submission assertion that header.ChannelHeader != nil in custom tooling.","Watch for proto marshal options that omit empty fields when embedding header bytes."],"tags":["hyperledger-fabric","ordering","protobuf","envelope-validation"],"backgroundTag":"missing-message-header","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"}