MyCATApache/Mycat-Server · error · java.lang.RuntimeException

cannot get the slaveID for dataHost

Error message

cannot get the slaveID  for dataHost :${dbNode.getDbPool().getHostName()}

What it means

After loading slaveIDs and acquiring the ZK lock, getSlaveIdFromZKForDataNode tries to select a free slave ID (cross-checking ZooKeeper's slaveIDs registry and running tasks). If every attempt/branch fails to produce one, control falls through to a final unconditional RuntimeException 'cannot get the slaveID for dataHost :X'.

Solutions

  1. Inspect ZooKeeper at the Mycat base path (slaveIDs/ and task nodes) for stale entries from old tasks and clean them up
  2. Check ZooKeeper connectivity and latency; retry the migrate command once ZK is healthy
  3. Add more read hosts (distinct serverIds) to the dataHost so free slave IDs exist
  4. Rerun the migration with fewer concurrent migrate tasks to avoid lock contention/ID exhaustion

Example fix

// before: stale ZK node blocks all IDs
/mycat/slaveIDs/host1/3  (from a crashed task)
// after: delete stale node / release lock, then rerun
zkCli.sh delete /mycat/slaveIDs/host1/3
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: confirm free slave IDs exist in ZK before starting a migration
List<Integer> claimed = zk.getChildren(ZKUtils.getZKBasePath() + "slaveIDs/" + dataHost, false)
    .stream().map(Integer::parseInt).collect(toList());
if (claimed.containsAll(allSlaveIDList)) throw new IllegalStateException("no free slaveID for " + dataHost);

Try / catch

catch (RuntimeException e) { if (e.getMessage().startsWith("cannot get the slaveID")) { /* clean stale ZK entries, ensure ZK reachable, retry with backoff */ } throw e; }

Prevention

When it happens

Trigger: Migrate command runs; slaveIDs are configured but no usable slave ID can be obtained — all slave IDs are already claimed in ZooKeeper by other tasks, the 30s inter-process semaphore lock can't be acquired in time, or ZK lookups fail so the selection loop never assigns an ID.

Common situations: Concurrent migrate tasks exhausting free slave IDs; stale ZK state from crashed runs holding IDs; ZooKeeper connectivity/latency causing lock timeouts; replica serverIds conflicting with other hosts' registrations.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/io/mycat/server/handler/MigrateHandler.java:399

                }
            }
            for (Integer integer : allSlaveIDList) {
                if (!zkSlaveIdsSet.contains(integer)) {
                    ZKUtils.getConnection().create().creatingParentsIfNeeded().forPath(taskPath + "/" + integer);
                    return integer;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                slaveIDsLock.release();
            } catch (Exception e) {
                LOGGER.error("error:", e);
            }
        }

        throw new RuntimeException("cannot get the slaveID  for dataHost :" + dbNode.getDbPool().getHostName());
    }

    private static List<Integer> parseSlaveIDs(String slaveIDs) {
        List<Integer> allSlaveList = new ArrayList<>();
        List<String> stringList = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(slaveIDs);
        for (String id : stringList) {
            if (id.contains("-")) {
                List<String> idRangeList = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(id);
                if (idRangeList.size() != 2)
                    throw new RuntimeException(id + "slaveIds range must be 2  size");
                for (int i = Integer.parseInt(idRangeList.get(0)); i <= Integer.parseInt(idRangeList.get(1)); i++) {
                    allSlaveList.add(i);
                }

            } else {
                allSlaveList.add(Integer.parseInt(id));
            }
        }

View on GitHub (pinned to 65f8d8beb7)