{"record":{"id":"c3cb158713d84173","repo":"hyperledger/fabric","slug":"attempted-to-change-consensus-type-from-s-to-s-c3cb15","errorCode":null,"errorMessage":"attempted to change consensus type from %s to %s, transition not supported","messagePattern":"attempted to change consensus type from (.+?) to (.+?), transition not supported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/msgprocessor/maintenancefilter.go","lineNumber":133,"sourceCode":"\t\t\treturn errors.Errorf(\"attempted to change ConsensusType.Metadata, but ConsensusType.State is changing from %s to %s\",\n\t\t\t\tordererConfig.ConsensusState(), nextOrdererConfig.ConsensusState())\n\t\t}\n\t}\n\n\t// ConsensusType.Type can only change in maintenance-mode, and only within the set of permitted types.\n\t// Note: only etcdraft to BFT transitions are supported.\n\tif ordererConfig.ConsensusType() != nextOrdererConfig.ConsensusType() {\n\t\tif ordererConfig.ConsensusState() == orderer.ConsensusType_STATE_NORMAL {\n\t\t\treturn errors.Errorf(\"attempted to change consensus type from %s to %s, but current config ConsensusType.State is not in maintenance mode\",\n\t\t\t\tordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())\n\t\t}\n\t\tif nextOrdererConfig.ConsensusState() == orderer.ConsensusType_STATE_NORMAL {\n\t\t\treturn errors.Errorf(\"attempted to change consensus type from %s to %s, but next config ConsensusType.State is not in maintenance mode\",\n\t\t\t\tordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())\n\t\t}\n\n\t\tif !mf.permittedTargetConsensusTypes[nextOrdererConfig.ConsensusType()] {\n\t\t\treturn errors.Errorf(\"attempted to change consensus type from %s to %s, transition not supported\",\n\t\t\t\tordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())\n\t\t}\n\n\t\tif nextOrdererConfig.ConsensusType() == \"BFT\" {\n\t\t\tupdatedMetadata := &smartbft.Options{}\n\t\t\tif err := proto.Unmarshal(nextOrdererConfig.ConsensusMetadata(), updatedMetadata); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"failed to unmarshal BFT metadata configuration\")\n\t\t\t}\n\n\t\t\t_, err := util.ConfigFromMetadataOptions(1, updatedMetadata)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.New(\"invalid BFT metadata configuration\")\n\t\t\t}\n\n\t\t\terr = validateBFTConsenterMapping(ordererConfig, nextOrdererConfig)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"invalid BFT consenter mapping configuration\")\n\t\t\t}","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/msgprocessor/maintenancefilter.go#L115-L151","documentation":"Thrown by inspect in the maintenance filter when a config update tries to change the consensus type to a type that is not in mf.permittedTargetConsensusTypes, even though both current and next configs are in maintenance mode. The orderer only allows transitions to explicitly permitted target consensus types, so unsupported direct transitions are rejected.","triggerScenarios":"In maintenance mode, submitting a config update whose Orderer group changes consensus type to a value not whitelisted as a permitted target (e.g. an unsupported type string, or a transition the deployment does not allow).","commonSituations":"Attempting a consensus type migration to a consensus plugin the network does not support (e.g. solo to something on newer versions where it was removed), or a typo in the consensus type name in the config update.","solutions":["Use a supported target consensus type for the migration (e.g. etcdraft or BFT as permitted by your Fabric version)","Check the permittedTargetConsensusTypes configured on the orderers and align the update with it","Fix the consensus type spelling in the config update if it was a typo","If a multi-hop transition is needed, migrate through an intermediate permitted type in separate maintenance-mode updates"],"exampleFix":"// before: unsupported transition\n\"ConsensusType\": { \"State\": \"STATE_MAINTENANCE\", \"Type\": \"solo\" }\n// after: permitted target type\n\"ConsensusType\": { \"State\": \"STATE_MAINTENANCE\", \"Type\": \"BFT\" }","handlingStrategy":"validation","validationCode":"var permitted = map[string]bool{\"etcdraft\": true, \"BFT\": true}\nif next.Type != cur.Type && !permitted[next.Type] {\n    return fmt.Errorf(\"target consensus type %q is not a permitted migration target\", next.Type)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check your Fabric version's supported migration targets before planning the migration","Copy the consensus type string exactly as supported (case-sensitive, e.g. \"BFT\")","Plan multi-hop migrations as separate maintenance-mode updates"],"tags":["hyperledger-fabric","orderer","consensus-migration","config-update"],"backgroundTag":"consensus-type-transition-not-supported","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"}