alibaba/canal · error · CanalServerException
ClientIdentity:%s should subscribe first
Error message
ClientIdentity:%s should subscribe first
What it means
Thrown by the private checkSubscribe() guard, which is invoked at the top of get()/ack()/rollback() before any batch operation. It asks MetaManager.hasSubscribe(clientIdentity); if false it aborts because batch tracking and cursor positioning require an active subscription for that destination+clientId.
Source
Thrown at server/src/main/java/com/alibaba/otter/canal/server/embedded/CanalServerWithEmbedded.java:527
return eventStore.tryGet(start, batchSize);
} else {
try {
if (timeout <= 0) {
return eventStore.get(start, batchSize);
} else {
return eventStore.get(start, batchSize, timeout, unit);
}
} 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()) {View on GitHub (pinned to 87be50e876)
Solutions
- Call server.subscribe(clientIdentity) and wait for it to succeed before any get/ack/rollback.
- Verify the destination string in the ClientIdentity matches exactly between subscribe and subsequent calls.
- If using a memory MetaManager, re-subscribe after every server restart; use ZooKeeper MetaManager for persistence.
- Add a subscription readiness check in client startup before entering the consume loop.
Example fix
// before: get without subscribe ClientIdentity cid = new ClientIdentity(destination, clientId); Message msg = server.get(cid, 1000, 1L, TimeUnit.SECONDS); // after: subscribe first ClientIdentity cid = new ClientIdentity(destination, (short) 1001); server.subscribe(cid); // register subscription Message msg = server.get(cid, 1000, 1L, TimeUnit.SECONDS);
Defensive patterns
Strategy: validation
Validate before calling
// verify subscription exists before any batch operation
if (!metaManager.hasSubscribe(clientIdentity)) {
server.subscribe(clientIdentity);
} Try / catch
try {
server.get(clientId, batchSize, timeout, unit);
} catch (CanalServerException e) {
if (e.getMessage().contains("should subscribe first")) {
server.subscribe(clientId);
return server.get(clientId, batchSize, timeout, unit);
}
throw e;
} Prevention
- Centralize client connect logic so subscribe always precedes get/ack/rollback.
- Use a ZooKeeper-backed MetaManager so subscriptions survive server restarts.
- Assert destination name consistency between subscribe and consume paths in tests.
When it happens
Trigger: Calling get(), ack(), or rollback() on a ClientIdentity whose subscribe(destination, filter) was never called, was called for a different destination, or whose subscription was cleared. Also fires if the MetaManager lost the subscription record (e.g. in-memory MetaManager after a server restart).
Common situations: Client connects and immediately calls get() without subscribe(); client subscribes to destination A then queries destination B; server restart with a memory-backed MetaManager (no ZooKeeper) wipes subscriptions; typo in destination name between subscribe and get.
Related errors
- destination:%s should start first
- {} has startup , don't repeat start
- {} isn't start , please check
- zk client has already been started
- Disconnect pulsar consumer error
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/b8f67dc390152fcc.
Report an issue: GitHub.