alibaba/canal · warning · RuntimeException
count is not supportted in tablestore
Error message
count is not supportted in tablestore
What it means
The TablestoreAdapter unconditionally throws this from the count() method override, because Alibaba Tablestore (OTS) does not provide a native count/aggregate API. The method exists to satisfy the CanalAdapter interface contract but is intentionally unimplemented. Any caller that invokes count() on a tablestore adapter will hit this immediately.
Source
Thrown at client-adapter/tablestore/src/main/java/com/alibaba/otter/canal/client/adapter/tablestore/TablestoreAdapter.java:243
config.setAllowDuplicatedRowInBatchRequest(true);
config.setConcurrency(8);
config.setWriteMode(WriteMode.PARALLEL);
TableStoreWriter writer = new DefaultTableStoreWriter(
properties.get(PropertyConstants.TABLESTORE_ENDPOINT),
credentials,
properties.get(PropertyConstants.TABLESTORE_INSTANCENAME),
mappingConfig.getDbMapping().getTargetTable(),
config,
null
);
return writer;
}
@Override
public Map<String, Object> count(String task) {
throw new RuntimeException("count is not supportted in tablestore");
}
@Override
public String getDestination(String task) {
MappingConfig config = tablestoreMapping.get(task);
if (config != null) {
return config.getDestination();
}
return null;
}
@Override
public void destroy() {
if (tablestoreSyncService != null) {
tablestoreSyncService.close();
}
View on GitHub (pinned to 87be50e876)
Solutions
- Do not call count() on a TablestoreAdapter — it is unsupported by design.
- If row counting is needed, query the OTS API separately using a RangeIterator or maintain a separate counter table.
- Guard the caller to skip tablestore adapters when invoking count(), checking the adapter type or catching this exception.
Example fix
// before: blindly calls count on all adapters
for (CanalAdapter adapter : adapters) {
Map<String, Object> counts = adapter.count(task);
}
// after: skip unsupported adapters
for (CanalAdapter adapter : adapters) {
if (!(adapter instanceof TablestoreAdapter)) {
Map<String, Object> counts = adapter.count(task);
}
} Defensive patterns
Strategy: type-guard
Validate before calling
null
Type guard
// Type guard: check adapter type before calling count
public static boolean supportsCount(CanalAdapter adapter) {
return !(adapter instanceof TablestoreAdapter);
}
// Usage:
if (supportsCount(adapter)) {
Map<String, Object> counts = adapter.count(task);
} Try / catch
try {
Map<String, Object> counts = adapter.count(task);
} catch (RuntimeException e) {
if ("count is not supportted in tablestore".equals(e.getMessage())) {
// expected for tablestore; skip
logger.debug("count() not supported by this adapter");
} else {
throw e;
}
} Prevention
- Do not call count() on TablestoreAdapter — it is unsupported by design.
- When iterating heterogeneous adapters, guard count() calls with an instanceof check.
- If counts are needed for monitoring, use OTS API directly or a separate counter mechanism.
When it happens
Trigger: Calling TablestoreAdapter.count(task) from any code path — typically from a monitoring endpoint, admin tool, or test that attempts to retrieve row counts from the target tablestore table.
Common situations: A monitoring script or canal-admin dashboard calls count() on all adapters including tablestore; automated tests iterate all adapter types and call count(); custom code that assumes all adapters support counting.
Related errors
- No tablestore adapter found for config key: {key}
- Failed rows:{rows}
- not allow to change outAdapterKey
- ERROR Config: {fileName} {errorMessage}
- dbMapping.database
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/a672057b65114cb0.
Report an issue: GitHub.