{"record":{"id":"810b65b03df55c1a","repo":"apache/seatunnel","slug":"failed-to-call-factoryidentifier-method","errorCode":null,"errorMessage":"Failed to call factoryIdentifier method.","messagePattern":"Failed to call factoryIdentifier method\\.","errorType":"exception","errorClass":"SeaTunnelEngineException","httpStatus":null,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/utils/FactoryUtil.java","lineNumber":56,"sourceCode":"            ClassLoader classLoader, Class<T> factoryClass, String factoryIdentifier) {\n        try {\n            final List<T> result = new LinkedList<>();\n            ServiceLoader.load(factoryClass, classLoader).iterator().forEachRemaining(result::add);\n\n            List<T> foundFactories =\n                    result.stream()\n                            .filter(f -> factoryClass.isAssignableFrom(f.getClass()))\n                            .filter(\n                                    t -> {\n                                        try {\n                                            return t.getClass()\n                                                    .getMethod(\"factoryIdentifier\")\n                                                    .invoke(t)\n                                                    .equals(factoryIdentifier);\n                                        } catch (IllegalAccessException\n                                                | InvocationTargetException\n                                                | NoSuchMethodException e) {\n                                            throw new SeaTunnelEngineException(\n                                                    \"Failed to call factoryIdentifier method.\");\n                                        }\n                                    })\n                            .collect(Collectors.toList());\n\n            if (foundFactories.isEmpty()) {\n                throw new SeaTunnelEngineException(\n                        String.format(\n                                \"Could not find any factories that implement '%s' in the classpath.\",\n                                factoryClass.getName()));\n            }\n\n            if (foundFactories.size() > 1) {\n                throw new SeaTunnelEngineException(\n                        String.format(\n                                \"Multiple factories for identifier '%s' that implement '%s' found in the classpath.\\n\\n\"\n                                        + \"Ambiguous factory classes are:\\n\\n\"\n                                        + \"%s\",","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/utils/FactoryUtil.java#L38-L74","documentation":"Thrown by FactoryUtil.discoverFactory while filtering SPI-discovered factory instances: it reflectively invokes each candidate's factoryIdentifier() method, and any IllegalAccessException, InvocationTargetException, or NoSuchMethodException is wrapped in a SeaTunnelEngineException. This indicates a factory on the classpath whose class is broken or does not expose the expected factoryIdentifier method.","triggerScenarios":"Calling FactoryUtil.discoverFactory(factoryClass, classLoader, identifier) when a plugin jar on the classpath contains a factory class missing the public factoryIdentifier() method, or whose factoryIdentifier() implementation itself throws (InvocationTargetException).","commonSituations":"A corrupted/mismatched plugin jar version where the factory interface changed; a custom factory implementing the wrong interface version; shaded jars with conflicting factory classes.","solutions":["Identify the offending factory jar by enabling the underlying cause (log at debug or temporarily catch InvocationTargetException to print its target exception) and remove/upgrade that plugin jar.","Ensure the plugin jar version matches your SeaTunnel engine version so the factory interface and its factoryIdentifier method align.","Rebuild any custom factory so it properly implements the current SeaTunnelFactory interface with a public factoryIdentifier() method.","Clean the plugins directory of duplicate or stale jars and reinstall connectors with install-plugin.sh."],"exampleFix":"// before: custom factory missing the interface method\nclass MySourceFactory { public String id() { return \"MySource\"; } }\n// after\npublic class MySourceFactory implements SeaTunnelSourceFactory {\n    @Override\n    public String factoryIdentifier() { return \"MySource\"; }\n}","handlingStrategy":"try-catch","validationCode":"// verify jar integrity: jar tf connector.jar must list META-INF/services factory entries and the factory class","typeGuard":"boolean isUsableFactory(Object t) { try { t.getClass().getMethod(\"factoryIdentifier\"); return true; } catch (NoSuchMethodException e) { return false; } }","tryCatchPattern":"try { FactoryUtil.discoverFactory(FactoryClass.class, classLoader, id); } catch (SeaTunnelEngineException e) { log.error(\"factory discovery failed, check plugin jars on classpath\", e); throw e; }","preventionTips":["Keep plugin jars at the same version as the SeaTunnel engine.","Wipe stale/duplicate jars from connectors/ before upgrading.","Implement custom factories against the exact Factory interface of your SeaTunnel version."],"tags":["spi","reflection","classpath","zeta-engine"],"backgroundTag":"method-not-implemented","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}