{"record":{"id":"e4825f624eb972fc","repo":"MyCATApache/Mycat-Server","slug":"writehost-hostname-duplicated","errorCode":null,"errorMessage":"writeHost ${hostName} duplicated!","messagePattern":"writeHost (.+?) duplicated!","errorType":"exception","errorClass":"ConfigException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/config/loader/xml/XMLSchemaLoader.java","lineNumber":837,"sourceCode":"\t\t\t}\n            //读取心跳语句\n            String heartbeatSQL = element.getElementsByTagName(\"heartbeat\").item(0).getTextContent();\n            //读取 初始化sql配置,用于oracle\n            NodeList connectionInitSqlList = element.getElementsByTagName(\"connectionInitSql\");\n            String initConSQL = null;\n            if (connectionInitSqlList.getLength() > 0) {\n                initConSQL = connectionInitSqlList.item(0).getTextContent();\n            }\n            //读取writeHost\n            NodeList writeNodes = element.getElementsByTagName(\"writeHost\");\n            DBHostConfig[] writeDbConfs = new DBHostConfig[writeNodes.getLength()];\n            Map<Integer, DBHostConfig[]> readHostsMap = new HashMap<Integer, DBHostConfig[]>(2);\n            Set<String> writeHostNameSet = new HashSet<String>(writeNodes.getLength());\n            for (int w = 0; w < writeDbConfs.length; w++) {\n                Element writeNode = (Element) writeNodes.item(w);\n                writeDbConfs[w] = createDBHostConf(name, writeNode, dbType, dbDriver, maxCon, minCon, filters, logTime);\n                if (writeHostNameSet.contains(writeDbConfs[w].getHostName())) {\n                    throw new ConfigException(\"writeHost \" + writeDbConfs[w].getHostName() + \" duplicated!\");\n                } else {\n                    writeHostNameSet.add(writeDbConfs[w].getHostName());\n                }\n                NodeList readNodes = writeNode.getElementsByTagName(\"readHost\");\n                //读取对应的每一个readHost\n                if (readNodes.getLength() != 0) {\n                    DBHostConfig[] readDbConfs = new DBHostConfig[readNodes.getLength()];\n                    Set<String> readHostNameSet = new HashSet<String>(readNodes.getLength());\n                    for (int r = 0; r < readDbConfs.length; r++) {\n                        Element readNode = (Element) readNodes.item(r);\n                        readDbConfs[r] = createDBHostConf(name, readNode, dbType, dbDriver, maxCon, minCon, filters, logTime);\n                        if (readHostNameSet.contains(readDbConfs[r].getHostName())) {\n                            throw new ConfigException(\"readHost \" + readDbConfs[r].getHostName() + \" duplicated!\");\n                        } else {\n                            readHostNameSet.add(readDbConfs[r].getHostName());\n                        }\n                    }\n                    readHostsMap.put(w, readDbConfs);","sourceCodeStart":819,"sourceCodeEnd":855,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/config/loader/xml/XMLSchemaLoader.java#L819-L855","documentation":"While building a dataHost's writeHost list, XMLSchemaLoader tracks writeHost 'host' attribute values in a HashSet. If two writeHost elements under the same dataHost share the same host name, it throws this ConfigException; write hostnames must be unique within a dataHost so failover/heartbeat logic can address them unambiguously.","triggerScenarios":"A <dataHost> contains two <writeHost> elements with identical host attributes; createDBHostConf returns a DBHostConfig whose getHostName() is already in writeHostNameSet.","commonSituations":"Copy-pasting a writeHost for a second master and forgetting to change host=\"hostM1\"; generating configs programmatically without a uniqueness check; backup master mistakenly given the same name as the primary.","solutions":["Open schema.xml, find the dataHost named in the message, and give each <writeHost> a distinct host attribute value","Verify any references (e.g., in monitoring scripts or switchType configs) that target the old duplicate name are updated","If hosts are generated by tooling, add uniqueness enforcement on the host attribute","Restart MyCat to reload the corrected configuration"],"exampleFix":"// before\n<writeHost host=\"hostM1\" url=\"10.0.0.1:3306\" .../>\n<writeHost host=\"hostM1\" url=\"10.0.0.2:3306\" .../>\n// after\n<writeHost host=\"hostM1\" url=\"10.0.0.1:3306\" .../>\n<writeHost host=\"hostM2\" url=\"10.0.0.2:3306\" .../>","handlingStrategy":"validation","validationCode":"// detect duplicate writeHost names per dataHost\nfor each dataHost element:\n  Set<String> seen = new HashSet<>();\n  NodeList ws = dh.getElementsByTagName(\"writeHost\");\n  for (int i = 0; i < ws.getLength(); i++) {\n      String h = ((Element) ws.item(i)).getAttribute(\"host\");\n      if (!seen.add(h)) throw new IllegalStateException(\"Duplicate writeHost \" + h);\n  }","typeGuard":"null","tryCatchPattern":"try {\n    schemaLoader.load();\n} catch (ConfigException e) {\n    LOG.error(\"Duplicate writeHost name: \" + e.getMessage());\n    throw new ConfigurationException(\"WriteHost host attributes must be unique per dataHost\", e);\n}","preventionTips":["Give every writeHost a globally distinct name, not just per-dataHost-unique","Enforce unique host names in any config-generation script","Review diffs of schema.xml for copied writeHost lines"],"tags":["configuration","xml","duplicate"],"backgroundTag":"conflicting-config-options","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}