{"record":{"id":"a698a19b50fb5cf6","repo":"hyperledger/fabric","slug":"unsupported-legacy-system-channel-header-type-v","errorCode":null,"errorMessage":"unsupported legacy system channel header type: %v","messagePattern":"unsupported legacy system channel header type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/etcdraft/util.go","lineNumber":168,"sourceCode":"// config type, i.e. HeaderType_ORDERER_TRANSACTION or HeaderType_CONFIG\nfunc ConfigEnvelopeFromBlock(block *common.Block) (*common.Envelope, error) {\n\tif block == nil {\n\t\treturn nil, errors.New(\"nil block\")\n\t}\n\n\tenvelope, err := protoutil.ExtractEnvelope(block, 0)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to extract envelope from the block\")\n\t}\n\n\tchannelHeader, err := protoutil.ChannelHeader(envelope)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"cannot extract channel header\")\n\t}\n\n\tswitch channelHeader.GetType() {\n\tcase int32(common.HeaderType_ORDERER_TRANSACTION):\n\t\treturn nil, errors.Errorf(\"unsupported legacy system channel header type: %v\", channelHeader.GetType())\n\tcase int32(common.HeaderType_CONFIG):\n\t\treturn envelope, nil\n\tdefault:\n\t\treturn nil, errors.Errorf(\"unexpected header type: %v\", channelHeader.GetType())\n\t}\n}\n\n// ConsensusMetadataFromConfigBlock reads consensus metadata updates from the configuration block\nfunc ConsensusMetadataFromConfigBlock(block *common.Block) (*etcdraft.ConfigMetadata, *orderer.ConsensusType, error) {\n\tif block == nil {\n\t\treturn nil, nil, errors.New(\"nil block\")\n\t}\n\n\tif !protoutil.IsConfigBlock(block) {\n\t\treturn nil, nil, errors.New(\"not a config block\")\n\t}\n\n\tconfigEnvelope, err := ConfigEnvelopeFromBlock(block)","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/etcdraft/util.go#L150-L186","documentation":"ConfigEnvelopeFromBlock rejects blocks whose header type is HeaderType_ORDERER_TRANSACTION, the legacy pre-v2.x system-channel envelope type. Since Fabric 2.x (single system-channel-free ordering), this function only accepts HeaderType_CONFIG, so an orderer-transaction envelope is surfaced as an unsupported legacy type.","triggerScenarios":"Passing a system-channel (orderer transaction) block into ConsensusMetadataFromConfigBlock/ConfigEnvelopeFromBlock — e.g. during onboarding a node that was handed a legacy system channel genesis/config block.","commonSituations":"Upgrading a Fabric 1.4 ordering service topology to 2.x and feeding old system-channel blocks into new code paths; joining a channel via the wrong block (system channel genesis instead of application config block).","solutions":["Use the application channel's config block, not the legacy system channel block, as the input.","Complete the migration off the system channel (Fabric 2.5 no-syschan flow: remove system channel with osnadmin channel join per channel).","If reading genesis material, generate per-channel genesis blocks with configtxgen instead of reusing system-channel blocks."],"exampleFix":"// before\nsysChanBlock := getBlock(systemChannelID, 0) // HeaderType_ORDERER_TRANSACTION\nmeta, _, err := ConsensusMetadataFromConfigBlock(sysChanBlock)\n\n// after\nappChanBlock := getBlock(\"mychannel\", 0) // HeaderType_CONFIG genesis block\nmeta, _, err := ConsensusMetadataFromConfigBlock(appChanBlock)","handlingStrategy":"validation","validationCode":"hdr, err := ConfigChannelHeader(block)\nif err != nil {\n    return err\n}\nif hdr.Type == int32(common.HeaderType_ORDERER_TRANSACTION) {\n    return errors.New(\"legacy system channel block; use an application channel config block\")\n}","typeGuard":"func isLegacySystemChannelBlock(block *common.Block) bool {\n    hdr, err := ConfigChannelHeader(block)\n    return err == nil && hdr.GetType() == int32(common.HeaderType_ORDERER_TRANSACTION)\n}","tryCatchPattern":"envelope, err := ConfigEnvelopeFromBlock(block)\nif err != nil {\n    if strings.Contains(err.Error(), \"unsupported legacy system channel header type\") {\n        return errors.New(\"migrate off the system channel; use per-channel config blocks\")\n    }\n    return err\n}","preventionTips":["After upgrading to Fabric 2.x+, never feed system-channel blocks into application channel flows.","Use osnadmin channel join / configtxgen per-channel genesis blocks instead of old system channel genesis.","Check header type explicitly before config parsing during onboarding."],"tags":["hyperledger-fabric","etcdraft","system-channel","migration"],"backgroundTag":"unsupported-legacy-system-channel","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"}