{"record":{"id":"2335a819f64b903d","repo":"alibaba/canal","slug":"not-allow-to-change-outadapterkey-2335a8","errorCode":null,"errorMessage":"not allow to change outAdapterKey","messagePattern":"not allow to change outAdapterKey","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"client-adapter/tablestore/src/main/java/com/alibaba/otter/canal/client/adapter/tablestore/TablestoreAdapter.java","lineNumber":327,"sourceCode":"        config2writerMap.put(configName, writer);\n    }\n\n    public boolean addConfig(String fileName, MappingConfig config) {\n        if (match(config)) {\n            tablestoreMapping.put(fileName, config);\n            addSyncConfigToCache(fileName, config);\n            FileName2KeyMapping.register(getClass().getAnnotation(SPI.class).value(), fileName,\n                    configuration.getKey());\n            return true;\n        }\n        return false;\n    }\n\n    public void updateConfig(String fileName, MappingConfig config) {\n        if (config.getOuterAdapterKey() != null && !config.getOuterAdapterKey()\n                .equals(configuration.getKey())) {\n            // 理论上不允许改这个 因为本身就是通过这个关联起Adapter和Config的\n            throw new RuntimeException(\"not allow to change outAdapterKey\");\n        }\n        tablestoreMapping.put(fileName, config);\n        addSyncConfigToCache(fileName, config);\n    }\n\n    public void deleteConfig(String fileName) {\n        tablestoreMapping.remove(fileName);\n        for (Map<String, MappingConfig> configMap : mappingConfigCache.values()) {\n            if (configMap != null) {\n                configMap.remove(fileName);\n            }\n        }\n        FileName2KeyMapping.unregister(getClass().getAnnotation(SPI.class).value(), fileName);\n    }\n\n    private boolean match(MappingConfig config) {\n        boolean sameMatch = config.getOuterAdapterKey() != null && config.getOuterAdapterKey()\n                .equalsIgnoreCase(configuration.getKey());","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/client-adapter/tablestore/src/main/java/com/alibaba/otter/canal/client/adapter/tablestore/TablestoreAdapter.java#L309-L345","documentation":"Thrown by TablestoreAdapter.updateConfig() when a config update provides an outerAdapterKey that differs from the adapter's own configuration.getKey(). The outerAdapterKey is the binding that links a mapping config to its adapter instance; changing it at runtime would orphan the config from its writer infrastructure and break the adapter-config relationship, so the adapter rejects the change.","triggerScenarios":"Calling updateConfig(fileName, config) where config.getOuterAdapterKey() is non-null and not equal to the adapter's configuration.getKey() — typically when a hot-reload of a modified mapping YAML introduces a different or incorrect outerAdapterKey.","commonSituations":"An operator edits a tablestore mapping YAML and inadvertently changes or removes the outerAdapterKey field; a config management tool pushes a new YAML with a corrected/mistyped key; copy-paste between environments (dev→prod) without updating the key.","solutions":["Ensure the updated mapping config's outerAdapterKey matches the adapter's existing configuration key exactly.","If the key genuinely needs to change, remove the old config first via deleteConfig(), then add the new one via addConfig() with the matching key.","Audit config file changes before hot-reloading — particularly the outerAdapterKey field."],"exampleFix":"// before: config update with mismatched key\n// adapter key: 'ts-prod'\n// config.getOuterAdapterKey(): 'ts-dev'\nadapter.updateConfig(fileName, config); // throws\n\n// after: ensure key matches\nconfig.setOuterAdapterKey(\"ts-prod\");\nadapter.updateConfig(fileName, config);","handlingStrategy":"validation","validationCode":"// Before calling updateConfig, verify the key matches\nif (config.getOuterAdapterKey() != null\n    && !config.getOuterAdapterKey().equals(configuration.getKey())) {\n    throw new IllegalStateException(\n        \"Cannot update config: outerAdapterKey '\" + config.getOuterAdapterKey()\n        + \"' does not match adapter key '\" + configuration.getKey() + \"'\");\n}\nadapter.updateConfig(fileName, config);","typeGuard":"null","tryCatchPattern":"try {\n    adapter.updateConfig(fileName, config);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"not allow to change outAdapterKey\")) {\n        logger.error(\"Config key mismatch on update. Expected: {}, got: {}\",\n            configuration.getKey(), config.getOuterAdapterKey());\n    }\n    throw e;\n}","preventionTips":["Never change outerAdapterKey in an existing config file — if the key must change, delete and re-add the config.","Validate config file diffs before hot-reloading, focusing on the outerAdapterKey field.","Use config templating tools that enforce consistent key values per environment."],"tags":["tablestore-adapter","config-key-mismatch","hot-reload","config-error"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}