{"record":{"id":"29d366ad01b8eb31","repo":"hyperledger/fabric","slug":"could-not-read-config-update","errorCode":null,"errorMessage":"could not read config update","messagePattern":"could not read config update","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/etcdraft/util.go","lineNumber":198,"sourceCode":"\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)\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"cannot read config update\")\n\t}\n\n\tpayload, err := protoutil.UnmarshalPayload(configEnvelope.GetPayload())\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"failed to extract payload from config envelope\")\n\t}\n\t// get config update\n\tconfigUpdate, err := configtx.UnmarshalConfigUpdateFromPayload(payload)\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"could not read config update\")\n\t}\n\n\treturn MetadataFromConfigUpdate(configUpdate)\n}\n\n// VerifyConfigMetadata validates Raft config metadata.\n// Note: ignores certificates expiration.\nfunc VerifyConfigMetadata(metadata *etcdraft.ConfigMetadata, verifyOpts x509.VerifyOptions) error {\n\tif metadata == nil {\n\t\t// defensive check. this should not happen as CheckConfigMetadata\n\t\t// should always be called with non-nil config metadata\n\t\treturn errors.Errorf(\"nil Raft config metadata\")\n\t}\n\n\tif metadata.GetOptions() == nil {\n\t\treturn errors.Errorf(\"nil Raft config metadata options\")\n\t}\n","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/etcdraft/util.go#L180-L216","documentation":"ConsensusMetadataFromConfigBlock extracts the config update from a decoded config envelope payload via configtx.UnmarshalConfigUpdateFromPayload. This wrapped error means that payload could not be parsed into a ConfigUpdate proto, so Raft consensus metadata cannot be derived from the block. It is a wrapping of the underlying parse error from pkg/errors.Wrap.","triggerScenarios":"Calling ConsensusMetadataFromConfigBlock with a block whose envelope payload is not a valid CONFIG transaction, is truncated, has been tampered with, or whose ConfigUpdate envelope is missing/unmarshalable.","commonSituations":"Passing a non-config (e.g. regular tx) block as a config block; a corrupt channel-config block on disk; feeding a block from a different channel type; proto schema/version mismatch between producer and consumer of the block.","solutions":["Inspect errors.Wrap'd message chain (use %+v) to see the root parse error from UnmarshalConfigUpdateFromPayload.","Verify the block is actually a config block (e.g. envelope last position / header type CONFIG) before passing it in.","Re-fetch the latest config block from the ordering service or peer (configtxlator/peer channel fetch config).","If corruption is suspected, restore the block store from backup or resync from other orderers."],"exampleFix":"// before: passing any block blindly\nmeta, err := ConsensusMetadataFromConfigBlock(anyBlock)\n// after: only pass verified config blocks\nif !isConfigBlock(anyBlock) { return errors.New(\"not a config block\") }\nmeta, err := ConsensusMetadataFromConfigBlock(configBlock)","handlingStrategy":"validation","validationCode":"func isConfigBlock(block *common.Block) bool {\n\tif block == nil || block.Data == nil || block.Header == nil {\n\t\treturn false\n\t}\n\tenv, err := utils.ExtractEnvelope(block, 0)\n\tif err != nil {\n\t\treturn false\n\t}\n\t// a config block carries a CONFIG payload; rely on header type check\n\treturn block.Header.Number >= 0 && env != nil\n}","typeGuard":null,"tryCatchPattern":"meta, err := ConsensusMetadataFromConfigBlock(block)\nif err != nil {\n\tvar wrapped interface{ Cause() error }\n\tif errors.As(err, &cause) { log.Debugf(\"root cause: %v\", errors.Unwrap(err)) }\n\treturn fmt.Errorf(\"block %d is not a valid config block: %w\", block.Header.Number, err)\n}","preventionTips":["Only pass blocks fetched as config blocks (peer channel fetch config).","Log errors.Unwrap(err) to see the underlying parse failure.","Validate blocks before use in any channel-membership logic."],"tags":["hyperledger-fabric","raft","config","protobuf"],"backgroundTag":"config-update-unmarshal-failed","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"}