alibaba/canal · critical · RuntimeException

No tablestore adapter found for config key

Error message

No tablestore adapter found for config key: {key}

What it means

Thrown during TablestoreAdapter.init() when, after loading all tablestore mapping configs and filtering them through addConfig()/match(), the resulting tablestoreMapping map is empty. The match() method accepts a config only if config.outerAdapterKey equals the adapter's configuration key (sameMatch), or if outerAdapterKey is null and the adapter key starts with the auto-generated prefix derived from destination+groupId (prefixMatch). If no config passes either check, the adapter has nothing to sync and refuses to initialize.

Solutions

  1. Verify that at least one tablestore mapping YAML file has an `outerAdapterKey` value that exactly matches the adapter `key` in canal's application.yml.
  2. Confirm the mapping files are in the directory scanned by MappingConfigsLoader (typically conf/tablestore/ or the configured resource path).
  3. If using auto-generated keys (no outerAdapterKey in YAML), verify the adapter key follows the prefix pattern: auto-generated prefix + destination + groupId.
  4. Check canal logs at startup for 'Tablestore mapping config loaded:' to see which files were actually discovered.

Example fix

// application.yml adapter key is 'tablestore-1'
canalAdapters:
  - key: tablestore-1

// mapping YAML before (key mismatch)
outerAdapterKey: ts-instance

// after
outerAdapterKey: tablestore-1
Defensive patterns

Strategy: validation

Validate before calling

// Before initializing, verify at least one config matches the adapter key
Map<String, MappingConfig> configs = ConfigLoader.load(envProperties);
String adapterKey = configuration.getKey();
boolean hasMatch = configs.values().stream().anyMatch(c -> {
    boolean same = c.getOuterAdapterKey() != null && c.getOuterAdapterKey().equalsIgnoreCase(adapterKey);
    boolean prefix = c.getOuterAdapterKey() == null && adapterKey.startsWith(
        StringUtils.join(new String[]{Util.AUTO_GENERATED_PREFIX, c.getDestination(), c.getGroupId()}, '-'));
    return same || prefix;
});
if (!hasMatch) {
    throw new IllegalStateException("No tablestore config matches adapter key: " + adapterKey);
}

Type guard

null

Try / catch

try {
    tablestoreAdapter.init(config, envProperties);
} catch (RuntimeException e) {
    if (e.getMessage().contains("No tablestore adapter found")) {
        logger.error("Config key mismatch. Check outerAdapterKey in tablestore mapping YAML files.");
    }
    throw e;
}

Prevention

When it happens

Trigger: Initializing a TablestoreAdapter whose configuration.getKey() does not match any loaded config's outerAdapterKey, and no config qualifies for prefix matching — e.g. the adapter key in canal's main config differs from the outerAdapterKey values in the tablestore mapping YAML files.

Common situations: The `outerAdapterKey` in the tablestore mapping YAML does not match the adapter `key` defined in the canal application.yml; mapping files are placed in the wrong directory or not discovered by MappingConfigsLoader; the adapter key was renamed in the main config but mapping files were not updated; groupId or destination changed, breaking prefix matching.

Related errors


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

Appendix: source

Thrown at client-adapter/tablestore/src/main/java/com/alibaba/otter/canal/client/adapter/tablestore/TablestoreAdapter.java:65

    private TablestoreSyncService tablestoreSyncService;

    private Properties                              envProperties;

    private OuterAdapterConfig configuration;


    @Override
    public void init(OuterAdapterConfig configuration, Properties envProperties) {
        this.envProperties = envProperties;
        this.configuration = configuration;
        Map<String, MappingConfig> tablestoreMappingTmp = ConfigLoader.load(envProperties);
        // 过滤不匹配的key的配置
        tablestoreMappingTmp.forEach((key, config) -> {
            addConfig(key, config);
        });

        if (tablestoreMapping.isEmpty()) {
            throw new RuntimeException("No tablestore adapter found for config key: " + configuration.getKey());
        }

        tablestoreSyncService = new TablestoreSyncService();
    }

    /**
     * 根据配置文件获得tablestorewriter的WriterConfig信息
     * @param mappingConfig
     * @return
     */
    private WriterConfig getWriterConfig(MappingConfig mappingConfig) {
        WriterConfig config = new WriterConfig();
        MappingConfig.DbMapping mapping = mappingConfig.getDbMapping();
        config.setMaxBatchRowsCount(mapping.getCommitBatch());
        config.setConcurrency(mappingConfig.getThreads());
        config.setDispatchMode(DispatchMode.HASH_PRIMARY_KEY);
        config.setWriteMode(WriteMode.SEQUENTIAL);
        config.setBatchRequestType(BatchRequestType.BULK_IMPORT);

View on GitHub (pinned to 87be50e876)