{"record":{"id":"688e250fa1ab203d","repo":"apache/seatunnel","slug":"config-validation-failed-688e25","errorCode":"CONFIG_VALIDATION_FAILED","errorMessage":"PluginName: %s, PluginType: %s, Message: Cannot find Hudi catalog factory","messagePattern":"PluginName: (.+?), PluginType: (.+?), Message: Cannot find Hudi catalog factory","errorType":"error_code","errorClass":"HudiConnectorException","httpStatus":null,"severity":"critical","filePath":"seatunnel-connectors-v2/connector-hudi/src/main/java/org/apache/seatunnel/connectors/seatunnel/hudi/sink/HudiSink.java","lineNumber":113,"sourceCode":"\n    @Override\n    public Optional<Serializer<HudiCommitInfo>> getCommitInfoSerializer() {\n        return Optional.of(new DefaultSerializer<>());\n    }\n\n    @Override\n    public Optional<SaveModeHandler> getSaveModeHandler() {\n        TablePath tablePath =\n                TablePath.of(\n                        catalogTable.getTableId().getDatabaseName(),\n                        catalogTable.getTableId().getTableName());\n        CatalogFactory catalogFactory =\n                discoverFactory(\n                        Thread.currentThread().getContextClassLoader(),\n                        CatalogFactory.class,\n                        \"Hudi\");\n        if (catalogFactory == null) {\n            throw new HudiConnectorException(\n                    SeaTunnelAPIErrorCode.CONFIG_VALIDATION_FAILED,\n                    String.format(\n                            \"PluginName: %s, PluginType: %s, Message: %s\",\n                            getPluginName(), PluginType.SINK, \"Cannot find Hudi catalog factory\"));\n        }\n        Catalog catalog = catalogFactory.createCatalog(catalogFactory.factoryIdentifier(), config);\n        return Optional.of(\n                new DefaultSaveModeHandler(\n                        hudiSinkConfig.getSchemaSaveMode(),\n                        hudiSinkConfig.getDataSaveMode(),\n                        catalog,\n                        tablePath,\n                        catalogTable,\n                        null));\n    }\n\n    @Override\n    public Optional<CatalogTable> getWriteCatalogTable() {","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-hudi/src/main/java/org/apache/seatunnel/connectors/seatunnel/hudi/sink/HudiSink.java#L95-L131","documentation":"HudiSink.getSaveModeHandler() uses SeaTunnel's SPI discovery to locate the factory registered with identifier \"Hudi\". If discovery returns null — the Hudi catalog factory is not on the classpath or not registered as a service — a HudiConnectorException with CONFIG_VALIDATION_FAILED is thrown. SaveMode handling depends on creating the Hudi catalog through this factory.","triggerScenarios":"Running a job with save_mode requiring catalog handling while the connector-hudi plugin jar is absent from the runtime plugin directory, the SPI file is missing/broken, or the factory identifier lookup for \"Hudi\" fails on the current thread context classloader.","commonSituations":"Deploying only the sink jar without the full connector package; plugin.dir misconfigured so connector-hudi isn't loaded; custom classloader setups losing Thread.currentThread().getContextClassLoader(); manually assembled fat jars missing META-INF/services entries.","solutions":["Install the full connector-hudi plugin via sh bin/install-plugin.sh or copy the connector-hudi jar into the plugins directory.","Verify META-INF/services/org.apache.seatunnel.api.configuration.util.CatalogFactory (FactoryIdentifier SPI) entry for HudiCatalogFactory exists in the jar.","Check the plugin discovery directory configuration so the SeaTunnel runtime can see the connector jar.","Ensure the thread context classloader at job submission includes connector-hudi classes."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"Class<?> f = Thread.currentThread().getContextClassLoader()\n    .loadClass(\"org.apache.seatunnel.connectors.seatunnel.hudi.catalog.HudiCatalogFactory\");\n// if loadClass throws, the connector jar is not on the runtime classpath","typeGuard":null,"tryCatchPattern":"try {\n    sink.doWrite(...);\n} catch (HudiConnectorException e) {\n    if (e.getCode() == SeaTunnelAPIErrorCode.CONFIG_VALIDATION_FAILED) {\n        // verify plugin installation / SPI registration and resubmit\n    } else throw e;\n}","preventionTips":["Install connectors with bin/install-plugin.sh so all Hudi jars and SPI files are present.","Never hand-build connector jars without META-INF/services factory registrations.","Check plugin.dir configuration when deploying to a custom directory."],"tags":["hudi","spi","classpath","catalog-factory","plugin-discovery"],"backgroundTag":"missing-dependency","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"}