{"record":{"id":"827c2998931f42d3","repo":"hyperledger/fabric","slug":"updated-config-does-not-include-a-config-update","errorCode":null,"errorMessage":"updated config does not include a config update","messagePattern":"updated config does not include a config update","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/msgprocessor/maintenancefilter.go","lineNumber":81,"sourceCode":"\tif err != nil {\n\t\treturn errors.Wrap(err, \"envelope unmarshalling failed\")\n\t}\n\n\tlogger.Debugw(\"Going to inspect maintenance mode transition rules\",\n\t\t\"ConsensusState\", ordererConf.ConsensusState(), \"channel\", chanHdr.ChannelId)\n\terr = mf.inspect(configEnvelope, ordererConf)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"config transaction inspection failed\")\n\t}\n\n\treturn nil\n}\n\n// inspect checks whether the next orderer config, extracted from the incoming configEnvelope, respects the\n// transition rules of consensus-type migration using maintenance-mode.\nfunc (mf *MaintenanceFilter) inspect(configEnvelope *cb.ConfigEnvelope, ordererConfig channelconfig.Orderer) error {\n\tif configEnvelope.LastUpdate == nil {\n\t\treturn errors.Errorf(\"updated config does not include a config update\")\n\t}\n\n\tbundle, err := channelconfig.NewBundle(mf.support.ChannelID(), configEnvelope.Config, mf.bccsp)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to parse config\")\n\t}\n\n\tnextOrdererConfig, ok := bundle.OrdererConfig()\n\tif !ok {\n\t\treturn errors.New(\"next config is missing orderer group\")\n\t}\n\n\tif !ordererConfig.Capabilities().ConsensusTypeMigration() {\n\t\tif nextState := nextOrdererConfig.ConsensusState(); nextState != orderer.ConsensusType_STATE_NORMAL {\n\t\t\treturn errors.Errorf(\"next config attempted to change ConsensusType.State to %s, but capability is disabled\", nextState)\n\t\t}\n\t\tif ordererConfig.ConsensusType() != nextOrdererConfig.ConsensusType() {\n\t\t\treturn errors.Errorf(\"next config attempted to change ConsensusType.Type from %s to %s, but capability is disabled\",","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/msgprocessor/maintenancefilter.go#L63-L99","documentation":"MaintenanceFilter.inspect returns this when configEnvelope.LastUpdate is nil. The ConfigEnvelope carries the resulting Config plus the LastUpdate (the signed config-update envelope that produced it); a missing LastUpdate means the filter cannot verify that the state transition carries only the ConsensusType change. This typically indicates a hand-crafted or incorrectly constructed ConfigEnvelope.","triggerScenarios":"Submitting a cb.ConfigEnvelope with Config set but LastUpdate nil to the ordering service as a CONFIG transaction (e.g. building the envelope manually instead of via the configtxgen/configtxlator flow).","commonSituations":"Custom tooling that assembles ConfigEnvelope structs directly; tests that populate only Config; a serialization path that drops LastUpdate.","solutions":["Always set LastUpdate to the signed ConfigUpdateEnvelope when constructing a cb.ConfigEnvelope","Use the standard flow: create the update with configtxlator, wrap it, sign, and submit rather than assembling envelopes by hand","Check protoutil.CreateSignedEnvelope usage includes the ConfigEnvelope with both fields populated"],"exampleFix":"// before\nenv := &cb.ConfigEnvelope{Config: nextConfig}\n// after\nenv := &cb.ConfigEnvelope{Config: nextConfig, LastUpdate: signedConfigUpdateEnv}","handlingStrategy":"validation","validationCode":"if configEnvelope.LastUpdate == nil {\n\treturn errors.New(\"ConfigEnvelope.LastUpdate must reference the signed config-update envelope\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Populate both Config and LastUpdate when constructing ConfigEnvelope","Use configtxlator/configtxgen tooling rather than hand-built protos","Unit-test envelope construction before submitting to the network"],"tags":["ordering","config-envelope","maintenance-mode"],"backgroundTag":"missing-config-update-envelope","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"}