{"record":{"id":"5cf7180f207fd21d","repo":"apache/dolphinscheduler","slug":"duplicate-datasource-channel-named-s","errorCode":null,"errorMessage":"Duplicate datasource channel named '%s'","messagePattern":"Duplicate datasource channel named '(.+?)'","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-api/src/main/java/org/apache/dolphinscheduler/plugin/datasource/api/plugin/DataSourcePluginManager.java","lineNumber":68,"sourceCode":"    }\n\n    public static DataSourceProcessor getDataSourceProcessor(@NonNull DbType dbType) {\n        return dataSourceProcessorMap.get(dbType.getName());\n    }\n\n    public static void loadDataSourcePlugin() {\n        initializeDataSourceChannel();\n        initializeDataSourceProcessor();\n    }\n\n    private static synchronized void initializeDataSourceChannel() {\n        if (MapUtils.isNotEmpty(datasourceChannelMap)) {\n            return;\n        }\n        new PrioritySPIFactory<>(DataSourceChannelFactory.class).getSPIMap().forEach(\n                (dataSourceChannelName, dataSourceChannelFactory) -> {\n                    if (datasourceChannelMap.containsKey(dataSourceChannelName)) {\n                        throw new IllegalStateException(\n                                format(\"Duplicate datasource channel named '%s'\", dataSourceChannelName));\n                    }\n                    datasourceChannelMap.put(dataSourceChannelName, dataSourceChannelFactory.create());\n                    log.info(\"Registered datasource channel: {}\", dataSourceChannelName);\n                });\n    }\n\n    private static synchronized void initializeDataSourceProcessor() {\n        if (MapUtils.isNotEmpty(dataSourceProcessorMap)) {\n            return;\n        }\n\n        ServiceLoader.load(DataSourceProcessor.class).forEach(factory -> {\n            final String name = factory.getDbType().getName();\n            if (dataSourceProcessorMap.containsKey(name)) {\n                throw new IllegalStateException(format(\"Duplicate datasource processor named '%s'\", name));\n            }\n            DataSourceProcessor dataSourceProcessor = factory.create();","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-api/src/main/java/org/apache/dolphinscheduler/plugin/datasource/api/plugin/DataSourcePluginManager.java#L50-L86","documentation":"Thrown by DataSourcePluginManager when the SPI discovery mechanism finds two DataSourceChannelFactory implementations registered under the same channel name. The manager keeps a map keyed by channel name, so a duplicate would silently overwrite a plugin; it fails fast instead. This indicates a classpath/plugin packaging problem, not a user configuration issue.","triggerScenarios":"Calling loadDataSourcePlugin/initializeDataSourceChannel when two jars on the classpath both register a DataSourceChannelFactory with the same SPI name in META-INF/services (or duplicate SPI resource files), or the same plugin jar is loaded twice (e.g. copied into the libs dir twice).","commonSituations":"Deploying a custom datasource plugin that declares a name already used by a built-in plugin; fat-jar shading that merges duplicate META-INF/services entries; stale plugin jars left over after an upgrade in the plugins directory.","solutions":["Find the duplicate: list all jars providing META-INF/services/org.apache.dolphinscheduler.plugin.datasource.api.datasource.DataSourceChannelFactory and identify the duplicated name","Remove the redundant/stale plugin jar (e.g. duplicate or old-version jar in the plugins/libs directory)","If it is your custom plugin, rename the channel name returned by the factory's name() method to a unique value","Rebuild the fat jar with proper SPI merging (e.g. ServicesResourceTransformer in maven-shade-plugin) to deduplicate service files"],"exampleFix":"// before (custom plugin factory)\npublic String getName() { return \"mysql\"; }\n// after\npublic String getName() { return \"mysql-custom-v2\"; }","handlingStrategy":"try-catch","validationCode":"Set<String> seen = new HashSet<>();\nfor (String f : new File(pluginsDir).list((d,n)->n.endsWith(\".jar\"))) {\n  // scan jar for META-INF/services/...DataSourceChannelFactory names\n}\nif (seen.contains(myChannelName)) throw new IllegalStateException(\"name in use: \" + myChannelName);","typeGuard":"if (datasourceChannelMap.containsKey(dataSourceChannelName)) { log.warn(\"skipping duplicate channel {}\", dataSourceChannelName); return; }","tryCatchPattern":"try {\n  pluginManager.loadDataSourcePlugin();\n} catch (IllegalStateException e) {\n  if (e.getMessage().startsWith(\"Duplicate datasource channel\")) {\n    log.error(\"Duplicate SPI plugin name on classpath: {}\", e.getMessage());\n  } else throw e;\n}","preventionTips":["Keep only one version of each datasource plugin jar in the plugins directory","Use shade plugin ServicesResourceTransformer to merge META-INF/services","Give custom plugins unique channel names not colliding with built-ins","Clean stale jars after upgrades"],"tags":["spi","plugin-registration","duplicate-name","classpath"],"backgroundTag":"duplicate-plugin-registration","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}