{"record":{"id":"f7f26c6c511bf74d","repo":"hyperledger/fabric","slug":"illegal-orderer-config-detected-during-consensus-m","errorCode":null,"errorMessage":"illegal orderer config detected during consensus metadata validation: endpoints of org %s are missing","messagePattern":"illegal orderer config detected during consensus metadata validation: endpoints of org (.+?) are missing","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/etcdraft/chain.go","lineNumber":1474,"sourceCode":"// ValidateConsensusMetadata determines the validity of a\n// ConsensusMetadata update during config updates on the channel.\nfunc (c *Chain) ValidateConsensusMetadata(oldOrdererConfig, newOrdererConfig channelconfig.Orderer, newChannel bool) error {\n\tif newOrdererConfig == nil {\n\t\tc.logger.Panic(\"Programming Error: ValidateConsensusMetadata called with nil new channel config\")\n\t\treturn nil\n\t}\n\n\t// metadata was not updated\n\tif newOrdererConfig.ConsensusMetadata() == nil {\n\t\treturn nil\n\t}\n\n\tif newOrdererConfig.ConsensusType() != \"etcdraft\" {\n\t\tif newOrdererConfig.ConsensusType() == \"BFT\" {\n\t\t\t// This is a migration, so we have to validate the config change and make sure that endpoints per org are configured\n\t\t\tfor _, org := range newOrdererConfig.Organizations() {\n\t\t\t\tif len(org.Endpoints()) == 0 {\n\t\t\t\t\treturn errors.Errorf(\"illegal orderer config detected during consensus metadata validation: endpoints of org %s are missing\", org.Name())\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t} else {\n\t\t\tc.logger.Panicf(\"illegal consensus type detected during consensus metadata validation: %s\", newOrdererConfig.ConsensusType())\n\t\t\treturn errors.Errorf(\"illegal consensus type detected during consensus metadata validation: %s\", newOrdererConfig.ConsensusType())\n\n\t\t}\n\t}\n\n\tif oldOrdererConfig == nil {\n\t\tc.logger.Panic(\"Programming Error: ValidateConsensusMetadata called with nil old channel config\")\n\t\treturn nil\n\t}\n\n\tif oldOrdererConfig.ConsensusMetadata() == nil {\n\t\tc.logger.Panic(\"Programming Error: ValidateConsensusMetadata called with nil old metadata\")\n\t\treturn nil","sourceCodeStart":1456,"sourceCodeEnd":1492,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/etcdraft/chain.go#L1456-L1492","documentation":"Raised during consensus metadata validation when the channel is being migrated to a BFT consensus type but one of the organizations in the new orderer config has no consensus endpoints (hosts) defined. BFT requires every org to expose orderer endpoints so nodes can form the committee.","triggerScenarios":"A channel config update switches ConsensusType from etcdraft to BFT while an Organization() entry in Orderer.Config has an empty Endpoints() list in the new config.","commonSituations":"Admins preparing a consensus-type migration forget to add OrdererEndpoints for each org in the channel config; orgs added to the consenter set without endpoint configuration.","solutions":["Add OrdererEndpoints (host:port list) for every organization in the Orderer group of the new channel config.","Re-apply the config update using configtxlator to inject the missing endpoints.","Verify with configtxlator decode that each org's OrdererEndpoints is non-empty before resubmitting."],"exampleFix":"// configtx.yaml / channel config\nOrganizations:\n  - Name: Org1\n    # before\n    OrdererEndpoints: []\n    # after\n    OrdererEndpoints:\n      - orderer1.org1.example.com:7050","handlingStrategy":"validation","validationCode":"latestSeq := fetchCurrentConfigSequence(channel)\nif msgLastValidationSeq < latestSeq {\n    // recompute the config update against latest config before submitting\n    updated, err := recomputeConfigUpdate(latestConfig, desiredChange)\n    if err != nil { return err }\n    msg = signConfigUpdate(updated, adminCerts)\n}","typeGuard":null,"tryCatchPattern":"if strings.HasPrefix(err.Error(), \"bad config message:\") {\n    return rebuildAndResignConfigUpdate(channel, desiredChange)\n}","preventionTips":["Always rebuild config updates from the latest config seq.","Re-sign updates with current admin certificates.","Dry-run changes via configtxlator compare.","Avoid racing concurrent config updates."],"tags":["hyperledger-fabric","etcdraft","bft-migration","config-validation"],"backgroundTag":"missing-orderer-endpoints","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"}