alibaba/canal · error · CanalServerException
destination:%s should start first
Error message
destination:%s should start first
What it means
Thrown by the private checkStart() guard, called before checkSubscribe and every batch operation. It calls isStart(destination); if the CanalInstance for that destination is not in the canalInstances map / not started, the call aborts because there is no running pipeline to serve events.
Source
Thrown at server/src/main/java/com/alibaba/otter/canal/server/embedded/CanalServerWithEmbedded.java:534
}
} catch (Exception e) {
throw new CanalServerException(e);
}
}
}
private void checkSubscribe(ClientIdentity clientIdentity) {
CanalInstance canalInstance = canalInstances.get(clientIdentity.getDestination());
boolean hasSubscribe = canalInstance.getMetaManager().hasSubscribe(clientIdentity);
if (!hasSubscribe) {
throw new CanalServerException(String.format("ClientIdentity:%s should subscribe first",
clientIdentity.toString()));
}
}
private void checkStart(String destination) {
if (!isStart(destination)) {
throw new CanalServerException(String.format("destination:%s should start first", destination));
}
}
private void loadCanalMetrics() {
ServiceLoader<CanalMetricsProvider> providers = ServiceLoader.load(CanalMetricsProvider.class);
List<CanalMetricsProvider> list = new ArrayList<>();
for (CanalMetricsProvider provider : providers) {
list.add(provider);
}
if (list.isEmpty()) {
return;
}
// only allow ONE provider
if (list.size() > 1) {
logger.warn("Found more than one CanalMetricsProvider, use the first one.");
// 报告冲突View on GitHub (pinned to 87be50e876)
Solutions
- Confirm the destination is listed and successfully started: check server.getCanalInstances() / startup logs for the destination.
- Match the destination string exactly to the instance directory name under conf/.
- Fix any underlying instance start failure (DB connection, parser error) so the instance registers.
- Order startup so CanalServer.start() and per-instance start complete before clients connect.
Example fix
// before: client calls before instance ready
server.start(); // returns before instances are up
server.subscribe(cid);
// after: ensure destination started
server.start();
if (!server.isStart(destination)) {
throw new IllegalStateException("instance not started: " + destination);
}
server.subscribe(cid); Defensive patterns
Strategy: validation
Validate before calling
if (!server.isStart(destination)) {
throw new IllegalStateException(
"canal instance not started: " + destination + "; check canal.properties and instance config");
} Try / catch
try {
server.subscribe(clientId);
} catch (CanalServerException e) {
if (e.getMessage().contains("should start first")) {
throw new IllegalStateException("instance not ready, aborting client connect", e);
}
throw e;
} Prevention
- Gate client connections behind a readiness check that confirms isStart(destination).
- Monitor instance startup logs for the destination before opening clients.
- Keep destination strings identical in instance dir name, canal.properties, and client config.
When it happens
Trigger: Calling any client-facing method (get/ack/rollback/subscribe) for a destination whose CanalInstance was never started, was stopped, or whose name does not match a configured instance. The server must have called start(destination) or the instance must be auto-started at server startup.
Common situations: Destination name typo between canal instance config (canal.properties / instance.properties) and the client; instance failed to start at boot (e.g. DB connection error) leaving it absent; calling client APIs before CanalServerWithEmbedded.start() completes; instance stopped for maintenance.
Related errors
- ClientIdentity:%s should subscribe first
- bufferSize must be a power of 2
- canal.adminUser is empty , pls check https://github.com/alib
- canal.adminPasswd is empty , pls check https://github.com/al
- Start RocketMQ consumer error
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/3d2e9ef2ccbedabe.
Report an issue: GitHub.