alibaba/canal · error · ServiceException

empty cluster or server id

Error message

empty cluster or server id

What it means

Thrown by CanalInstanceServiceImpl.save() when clusterServerId is empty. The service expects a composite string prefixed 'cluster:' or 'server:' to derive the FK; an empty value cannot be resolved.

Source

Thrown at admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java:175

                .setDisableLazyLoading(true)
                .select("clusterId, serverId, name, modifiedTime")
                .where()
                // 暂停的实例也显示 .eq("status", "1")
                .eq("serverId", serverId)
                .findList();
            List<String> instanceList = Arrays.asList(instances);
            list.forEach(config -> {
                if (instanceList.contains(config.getName())) {
                    config.setRunningStatus("1");
                }
            });
            return list;
        }
    }

    public void save(CanalInstanceConfig canalInstanceConfig) {
        if (StringUtils.isEmpty(canalInstanceConfig.getClusterServerId())) {
            throw new ServiceException("empty cluster or server id");
        }
        if (canalInstanceConfig.getClusterServerId().startsWith("cluster:")) {
            Long clusterId = Long.parseLong(canalInstanceConfig.getClusterServerId().substring(8));
            canalInstanceConfig.setClusterId(clusterId);
        } else if (canalInstanceConfig.getClusterServerId().startsWith("server:")) {
            Long serverId = Long.parseLong(canalInstanceConfig.getClusterServerId().substring(7));
            canalInstanceConfig.setServerId(serverId);
        }

        try {
            String contentMd5 = SecurityUtil.md5String(canalInstanceConfig.getContent());
            canalInstanceConfig.setContentMd5(contentMd5);
        } catch (NoSuchAlgorithmException e) {
            // ignore
        }

        canalInstanceConfig.insert();
    }

View on GitHub (pinned to 87be50e876)

Solutions

  1. Set clusterServerId to either 'cluster:<id>' or 'server:<id>' before calling save().
  2. Validate the UI selection posts the composite key in the expected format.
  3. Add client-side validation requiring the field before submit.
  4. Inspect the request JSON to confirm clusterServerId is present and non-empty.

Example fix

// before
instanceConfig.setClusterServerId(""); // or null
service.save(instanceConfig);

// after
instanceConfig.setClusterServerId("cluster:3"); // or "server:5"
service.save(instanceConfig);
Defensive patterns

Strategy: validation

Validate before calling

if (StringUtils.isEmpty(canalInstanceConfig.getClusterServerId())
    || (!canalInstanceConfig.getClusterServerId().startsWith("cluster:")
        && !canalInstanceConfig.getClusterServerId().startsWith("server:"))) {
    throw new IllegalArgumentException("clusterServerId must be 'cluster:<id>' or 'server:<id>'");
}

Prevention

When it happens

Trigger: POST/PUT a new CanalInstanceConfig via the admin API without setting clusterServerId. The StringUtils.isEmpty check throws before the prefix parsing.

Common situations: Frontend form submitted without selecting a cluster or server; field renamed/missing in the payload; programmatic client forgot to set the composite id.

Related errors


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