{"record":{"id":"ccf797da13db8843","repo":"hyperledger/fabric","slug":"invalid-new-config-metadata","errorCode":null,"errorMessage":"invalid new config metadata","messagePattern":"invalid new config metadata","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/etcdraft/chain.go","lineNumber":1511,"sourceCode":"\t}\n\n\toldMetadata := &etcdraft.ConfigMetadata{}\n\tif err := proto.Unmarshal(oldOrdererConfig.ConsensusMetadata(), oldMetadata); err != nil {\n\t\tc.logger.Panicf(\"Programming Error: Failed to unmarshal old etcdraft consensus metadata: %v\", err)\n\t}\n\n\tnewMetadata := &etcdraft.ConfigMetadata{}\n\tif err := proto.Unmarshal(newOrdererConfig.ConsensusMetadata(), newMetadata); err != nil {\n\t\treturn errors.Wrap(err, \"failed to unmarshal new etcdraft metadata configuration\")\n\t}\n\n\tverifyOpts, err := createX509VerifyOptions(newOrdererConfig)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to create x509 verify options from old and new orderer config\")\n\t}\n\n\tif err := VerifyConfigMetadata(newMetadata, verifyOpts); err != nil {\n\t\treturn errors.Wrap(err, \"invalid new config metadata\")\n\t}\n\n\tif newChannel {\n\t\t// check if the consenters are a subset of the existing consenters (system channel consenters)\n\t\tset := ConsentersToMap(oldMetadata.GetConsenters())\n\t\tfor _, c := range newMetadata.GetConsenters() {\n\t\t\tif !set.Exists(c) {\n\t\t\t\treturn errors.New(\"new channel has consenter that is not part of system consenter set\")\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// create the dummy parameters for ComputeMembershipChanges\n\tc.raftMetadataLock.RLock()\n\tdummyOldBlockMetadata := proto.Clone(c.opts.BlockMetadata).(*etcdraft.BlockMetadata)\n\tc.raftMetadataLock.RUnlock()\n","sourceCodeStart":1493,"sourceCodeEnd":1529,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/etcdraft/chain.go#L1493-L1529","documentation":"This wrapper error is returned when VerifyConfigMetadata rejects the new etcdraft config metadata during a config update (orderer/consensus/etcdraft/chain.go:1511). The metadata is verified against the x509 verify options built from the orderer config, meaning every consenter's server/client TLS and intermediate certs must validate. It wraps the specific reason the metadata failed verification.","triggerScenarios":"A channel config update sets etcdraft consensus metadata whose consenters' TLS certificates do not verify against the orderer config's root CAs, or whose certificate/CA chains fail signature or expiration checks.","commonSituations":"Adding a new orderer consenter whose TLS cert was signed by a CA not in Orderer.TLS.RootCAs; expired consenter certificates; mismatched client/server cert pairs; editing metadata JSON by hand and breaking cert fields.","solutions":["Read the wrapped cause to identify which cert failed verification","Ensure every consenter TLS cert chains to a CA listed in Orderer.TLS.RootCAs","Replace expired certificates and resubmit the config update","Verify metadata structure (cert fields present, base64-PEM correct) with configtxlator"],"exampleFix":"// before\nconsenters: [{host: node1, port: 7050, client_tls_cert: certA, server_tls_cert: certB}] // certB signed by unknown CA\n// after\nconsenters: [{host: node1, port: 7050, client_tls_cert: certA, server_tls_cert: certA}] // both issued by root CA in Orderer.TLS.RootCAs","handlingStrategy":"validation","validationCode":"if err := VerifyConfigMetadata(newMetadata, verifyOpts); err != nil {\n    return fmt.Errorf(\"metadata rejected, fix certs against RootCAs: %w\", err)\n}","typeGuard":"func consenterCertsKnown(m *etcdraft.ConfigMetadata, rootCAs []*x509.Certificate) bool {\n    for _, c := range m.GetConsenters() {\n        if len(c.GetServerTlsCert()) == 0 || len(c.GetClientTlsCert()) == 0 { return false }\n    }\n    return len(rootCAs) > 0\n}","tryCatchPattern":"if err := submitConfigUpdate(cfg); err != nil {\n    if strings.Contains(err.Error(), \"invalid new config metadata\") {\n        // inspect wrapped cause: which cert/field failed verification\n    }\n}","preventionTips":["Issue all consenter certs from CAs listed in Orderer.TLS.RootCAs","Check cert expiry before proposing consenter changes","Validate metadata with configtxlator decode before update"],"tags":["raft","tls","metadata","config-update"],"backgroundTag":"consensus-metadata-invalid","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"}