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

  1. Confirm the destination is listed and successfully started: check server.getCanalInstances() / startup logs for the destination.
  2. Match the destination string exactly to the instance directory name under conf/.
  3. Fix any underlying instance start failure (DB connection, parser error) so the instance registers.
  4. 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

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


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