MyCATApache/Mycat-Server · error · ConfigException

writeHost duplicated!

Error message

writeHost ${hostName} duplicated!

What it means

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.

Solutions

  1. Open schema.xml, find the dataHost named in the message, and give each <writeHost> a distinct host attribute value
  2. Verify any references (e.g., in monitoring scripts or switchType configs) that target the old duplicate name are updated
  3. If hosts are generated by tooling, add uniqueness enforcement on the host attribute
  4. Restart MyCat to reload the corrected configuration

Example fix

// before
<writeHost host="hostM1" url="10.0.0.1:3306" .../>
<writeHost host="hostM1" url="10.0.0.2:3306" .../>
// after
<writeHost host="hostM1" url="10.0.0.1:3306" .../>
<writeHost host="hostM2" url="10.0.0.2:3306" .../>
Defensive patterns

Strategy: validation

Validate before calling

// detect duplicate writeHost names per dataHost
for each dataHost element:
  Set<String> seen = new HashSet<>();
  NodeList ws = dh.getElementsByTagName("writeHost");
  for (int i = 0; i < ws.getLength(); i++) {
      String h = ((Element) ws.item(i)).getAttribute("host");
      if (!seen.add(h)) throw new IllegalStateException("Duplicate writeHost " + h);
  }

Type guard

null

Try / catch

try {
    schemaLoader.load();
} catch (ConfigException e) {
    LOG.error("Duplicate writeHost name: " + e.getMessage());
    throw new ConfigurationException("WriteHost host attributes must be unique per dataHost", e);
}

Prevention

When it happens

Trigger: A <dataHost> contains two <writeHost> elements with identical host attributes; createDBHostConf returns a DBHostConfig whose getHostName() is already in writeHostNameSet.

Common situations: 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.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/e4825f624eb972fc. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/config/loader/xml/XMLSchemaLoader.java:837

			}
            //读取心跳语句
            String heartbeatSQL = element.getElementsByTagName("heartbeat").item(0).getTextContent();
            //读取 初始化sql配置,用于oracle
            NodeList connectionInitSqlList = element.getElementsByTagName("connectionInitSql");
            String initConSQL = null;
            if (connectionInitSqlList.getLength() > 0) {
                initConSQL = connectionInitSqlList.item(0).getTextContent();
            }
            //读取writeHost
            NodeList writeNodes = element.getElementsByTagName("writeHost");
            DBHostConfig[] writeDbConfs = new DBHostConfig[writeNodes.getLength()];
            Map<Integer, DBHostConfig[]> readHostsMap = new HashMap<Integer, DBHostConfig[]>(2);
            Set<String> writeHostNameSet = new HashSet<String>(writeNodes.getLength());
            for (int w = 0; w < writeDbConfs.length; w++) {
                Element writeNode = (Element) writeNodes.item(w);
                writeDbConfs[w] = createDBHostConf(name, writeNode, dbType, dbDriver, maxCon, minCon, filters, logTime);
                if (writeHostNameSet.contains(writeDbConfs[w].getHostName())) {
                    throw new ConfigException("writeHost " + writeDbConfs[w].getHostName() + " duplicated!");
                } else {
                    writeHostNameSet.add(writeDbConfs[w].getHostName());
                }
                NodeList readNodes = writeNode.getElementsByTagName("readHost");
                //读取对应的每一个readHost
                if (readNodes.getLength() != 0) {
                    DBHostConfig[] readDbConfs = new DBHostConfig[readNodes.getLength()];
                    Set<String> readHostNameSet = new HashSet<String>(readNodes.getLength());
                    for (int r = 0; r < readDbConfs.length; r++) {
                        Element readNode = (Element) readNodes.item(r);
                        readDbConfs[r] = createDBHostConf(name, readNode, dbType, dbDriver, maxCon, minCon, filters, logTime);
                        if (readHostNameSet.contains(readDbConfs[r].getHostName())) {
                            throw new ConfigException("readHost " + readDbConfs[r].getHostName() + " duplicated!");
                        } else {
                            readHostNameSet.add(readDbConfs[r].getHostName());
                        }
                    }
                    readHostsMap.put(w, readDbConfs);

View on GitHub (pinned to 65f8d8beb7)