{"record":{"id":"dc06bf38005c75e8","repo":"apache/seatunnel","slug":"elasticsearch-multi-table-writer-requires-elastics","errorCode":null,"errorMessage":"Elasticsearch multi-table writer requires ElasticsearchMultiTableResourceManager","messagePattern":"Elasticsearch multi-table writer requires ElasticsearchMultiTableResourceManager","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/sink/ElasticsearchSinkWriter.java","lineNumber":144,"sourceCode":"        // MultiTableSinkWriter injects one shared client after constructing all table writers.\n        // Standalone writers keep the existing fail-fast connection initialization behavior.\n        if (!(context instanceof SinkContextProxy)) {\n            initializeStandaloneClient();\n        }\n        context.registerFlushAction(this::timerFlush);\n    }\n\n    @Override\n    public MultiTableResourceManager<EsRestClient> initMultiTableResourceManager(\n            int tableSize, int queueSize) {\n        return new ElasticsearchMultiTableResourceManager();\n    }\n\n    @Override\n    public void setMultiTableResourceManager(\n            MultiTableResourceManager<EsRestClient> multiTableResourceManager, int queueIndex) {\n        if (!(multiTableResourceManager instanceof ElasticsearchMultiTableResourceManager)) {\n            throw new IllegalArgumentException(\n                    \"Elasticsearch multi-table writer requires ElasticsearchMultiTableResourceManager\");\n        }\n        releaseSharedClientResource();\n        closeOwnedClient();\n        ElasticsearchMultiTableResourceManager resourceManager =\n                (ElasticsearchMultiTableResourceManager) multiTableResourceManager;\n        try {\n            ElasticsearchMultiTableResourceManager.ClientResource clientResource =\n                    resourceManager.getOrCreateClientResource(config);\n            this.esRestClient = clientResource.getEsRestClient();\n            this.clusterInfo = clientResource.getClusterInfo();\n            this.multiTableResourceManager = resourceManager;\n            this.multiTableClientResource = clientResource;\n            this.ownsEsRestClient = false;\n            initializeSerializer(initialRowType);\n        } catch (RuntimeException | Error e) {\n            // A failed injection aborts MultiTableSinkWriter construction, whose close lifecycle\n            // will not run. Close every cached connection group before propagating the failure.","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/sink/ElasticsearchSinkWriter.java#L126-L162","documentation":"ElasticsearchSinkWriter.setMultiTableResourceManager validates that the provided MultiTableResourceManager is an ElasticsearchMultiTableResourceManager. Any other implementation cannot supply the ES clients the writer needs, so it throws IllegalArgumentException before adopting the resource.","triggerScenarios":"The engine/framework passes a MultiTableResourceManager<EsRestClient> that is not the Elasticsearch-specific implementation into setMultiTableResourceManager, typically in multi-table sink setups or tests exercising resource-manager wiring.","commonSituations":"Custom/engine changes supplying a generic resource manager; mismatched connector/engine versions where the ES resource manager class differs; unit tests passing stub implementations.","solutions":["Ensure the engine creates ElasticsearchMultiTableResourceManager for ES multi-table sinks","Align connector and engine versions so the resource manager types match","In tests, pass an actual ElasticsearchMultiTableResourceManager (with real or mocked EsRestClient) instead of a generic stub"],"exampleFix":"// before\nMultiTableResourceManager<EsRestClient> rm = new GenericResourceManager<>(client);\nwriter.setMultiTableResourceManager(rm, 0);\n// after\nElasticsearchMultiTableResourceManager rm = new ElasticsearchMultiTableResourceManager(clients);\nwriter.setMultiTableResourceManager(rm, 0);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"if (!(rm instanceof ElasticsearchMultiTableResourceManager)) {\n    throw new IllegalArgumentException(\"Expected ElasticsearchMultiTableResourceManager, got \" + rm.getClass());\n}","tryCatchPattern":null,"preventionTips":["Use the connector's own ElasticsearchMultiTableResourceManager in tests and custom wiring","Keep engine and connector versions in sync","Assert resource-manager type in unit tests before invoking the writer"],"tags":["elasticsearch","sink","multi-table","argument-type"],"backgroundTag":"invalid-argument-value","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"}