alibaba/canal · error · CanalParseException

Unknown host

Error message

Unknown host

What it means

generateUniqueServerId() calls InetAddress.getLocalHost(); if the host's name cannot be resolved to an address, the JVM throws UnknownHostException and canal wraps it in CanalParseException("Unknown host"). The server id is derived from the local host IP bytes, so host resolution is mandatory when slaveId is not explicitly set.

Source

Thrown at parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlEventParser.java:336

    private final long generateUniqueServerId() {
        try {
            // a=`echo $masterip|cut -d\. -f1`
            // b=`echo $masterip|cut -d\. -f2`
            // c=`echo $masterip|cut -d\. -f3`
            // d=`echo $masterip|cut -d\. -f4`
            // #server_id=`expr $a \* 256 \* 256 \* 256 + $b \* 256 \* 256 + $c
            // \* 256 + $d `
            // #server_id=$b$c$d
            // server_id=`expr $b \* 256 \* 256 + $c \* 256 + $d `
            InetAddress localHost = InetAddress.getLocalHost();
            byte[] addr = localHost.getAddress();
            int salt = (destination != null) ? destination.hashCode() : 0;
            return ((0x7f & salt) << 24) + ((0xff & (int) addr[1]) << 16) // NL
                   + ((0xff & (int) addr[2]) << 8) // NL
                   + (0xff & (int) addr[3]);
        } catch (UnknownHostException e) {
            throw new CanalParseException("Unknown host", e);
        }
    }

    protected EntryPosition findStartPosition(ErosaConnection connection) throws IOException {
        if (isGTIDMode()) {
            // GTID模式下,CanalLogPositionManager里取最后的gtid,没有则取instance配置中的
            LogPosition logPosition = getLogPositionManager().getLatestIndexBy(destination);
            if (logPosition != null) {
                // 如果以前是非GTID模式,后来调整为了GTID模式,那么为了保持兼容,需要判断gtid是否为空
                if (StringUtils.isNotEmpty(logPosition.getPostion().getGtid())) {
                    return logPosition.getPostion();
                }
            } else {
                if (masterPosition != null && StringUtils.isNotEmpty(masterPosition.getGtid())) {
                    return masterPosition;
                }
            }
        }

View on GitHub (pinned to 87be50e876)

Solutions

  1. Set canal.instance.slaveId explicitly to a unique positive integer so generateUniqueServerId() is never called.
  2. Ensure /etc/hosts contains an entry mapping the host's hostname to 127.0.0.1 (or its real IP).
  3. Fix DNS/resolution so `hostname -f` and InetAddress.getLocalHost() succeed.

Example fix

# /etc/hosts — ensure the container's hostname resolves
127.0.0.1   localhost my-canal-host
# or set slaveId explicitly in instance.properties
canal.instance.slaveId=12345
Defensive patterns

Strategy: validation

Validate before calling

// Avoid relying on InetAddress.getLocalHost()
if (slaveId <= 0) {
    slaveId = readConfiguredSlaveId(); // from canal.instance.slaveId
    if (slaveId <= 0) {
        // sanity: ensure host resolution works before dump
        try { InetAddress.getLocalHost(); }
        catch (UnknownHostException uhe) {
            throw new IllegalStateException("Cannot resolve local host and no canal.instance.slaveId set. Fix /etc/hosts or set slaveId.", uhe);
        }
    }
}

Prevention

When it happens

Trigger: canal.instance.slaveId is unset (<=0) and the container/host lacks a resolvable hostname in /etc/hosts or DNS. InetAddress.getLocalHost() then fails.

Common situations: Running canal in a minimal container without a localhost entry for its own hostname; a misconfigured /etc/hosts; DNS unreachable at startup.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/7d2a8b070a9f9511. Report an issue: GitHub.