{"record":{"id":"eec93e9d6ef9fdee","repo":"alibaba/canal","slug":"not-allow-to-change-outadapterkey-eec93e","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/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/KuduAdapter.java","lineNumber":218,"sourceCode":"        configMap.put(configName, mappingConfig);\n    }\n\n    public boolean addConfig(String fileName, KuduMappingConfig config) {\n        if (match(config)) {\n            kuduMapping.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, KuduMappingConfig 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        kuduMapping.put(fileName, config);\n        addSyncConfigToCache(fileName, config);\n    }\n\n    public void deleteConfig(String fileName) {\n        kuduMapping.remove(fileName);\n        for (Map<String, KuduMappingConfig> 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(KuduMappingConfig config) {\n        boolean sameMatch = config.getOuterAdapterKey() != null && config.getOuterAdapterKey()\n                .equalsIgnoreCase(configuration.getKey());","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/KuduAdapter.java#L200-L236","documentation":"Thrown by KuduAdapter.updateConfig() when a hot-reloaded kudu mapping yml carries an outerAdapterKey that differs from the key this adapter was initialized with (configuration.getKey()). The comment explains outerAdapterKey is the join between Adapter and Config and must stay fixed for the adapter's lifetime, so mutating it mid-run is rejected.","triggerScenarios":"KuduConfigMonitor detects a changed kudu yml file at runtime and calls updateConfig(fileName, config); the new config's outerAdapterKey is non-null and not equal to configuration.getKey().","commonSituations":"An operator edits the 'outerAdapterKey:' line of a running kudu mapping file to point at a different adapter. A file is copied between adapter config dirs and the monitor reloads it under the wrong adapter.","solutions":["Do not change 'outerAdapterKey:' in a mapping yml while the adapter is running; revert the edit so it matches the adapter's key.","If the key genuinely must change, stop the adapter/launcher, update application.yml and the yml consistently, then restart so init() rebinds.","Keep a single source of truth for adapter keys so hot-edits cannot diverge."],"exampleFix":"# before (running adapter bound to key 'kudu')\nouterAdapterKey: kudu2   # triggers error on hot reload\n# after\nouterAdapterKey: kudu    # keep stable; restart to change it","handlingStrategy":"validation","validationCode":"// In a hot-reload path, reject key changes before calling updateConfig.\nif (config.getOuterAdapterKey() != null\n        && !config.getOuterAdapterKey().equals(configuration.getKey())) {\n    logger.warn(\"Refusing to reload {}: outerAdapterKey changed ({} != {}). Restart to rebind.\",\n        fileName, config.getOuterAdapterKey(), configuration.getKey());\n    return; // skip instead of letting updateConfig throw\n}","typeGuard":null,"tryCatchPattern":"try {\n    adapter.updateConfig(fileName, newConfig);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"not allow to change outAdapterKey\")) {\n        logger.warn(\"Skipped hot reload of {}: outerAdapterKey immutable at runtime\", fileName);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Never edit 'outerAdapterKey:' on a running adapter; only edit mapping details.","If you must re-key an adapter, do it through a full restart, not the monitor.","Document outerAdapterKey as immutable in your config templates."],"tags":["kudu","config-update","hot-reload","canal"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}