{"record":{"id":"3ec5e5a88661c8cf","repo":"elastic/elasticsearch","slug":"not-supported-api","errorCode":null,"errorMessage":"Not Supported API","messagePattern":"Not Supported API","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java","lineNumber":311,"sourceCode":"        if (testDistribution == TestDistribution.INTEG_TEST) {\n            distribution.setType(ElasticsearchDistributionTypes.INTEG_TEST_ZIP);\n            // we change the underlying distribution when changing the test distribution of the cluster.\n            distribution.setPlatform(null);\n            distribution.setBundledJdk(null);\n        } else {\n            distribution.setType(ElasticsearchDistributionTypes.ARCHIVE);\n        }\n    }\n\n    @Override\n    public void plugin(Provider<RegularFile> plugin) {\n        checkFrozen();\n        this.plugins.add(plugin.map(RegularFile::getAsFile));\n    }\n\n    @Override\n    public void plugin(String pluginProjectPath) {\n        throw new UnsupportedOperationException(\"Not Supported API\");\n    }\n\n    public void plugin(TaskProvider<Zip> plugin) {\n        throw new UnsupportedOperationException(\"Not Supported API\");\n    }\n\n    @Override\n    public void module(Provider<RegularFile> module) {\n        checkFrozen();\n        this.modules.add(module.map(RegularFile::getAsFile));\n    }\n\n    /**\n     * Adds a module directory directly from a plain file provider.\n     * Used by {@link ElasticsearchCluster} when wiring a {@link org.gradle.api.tasks.Sync} task output,\n     * where the destination directory is already resolved as a {@link java.io.File} and does not need\n     * to go through the {@code Provider<RegularFile>} abstraction.\n     */","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java#L293-L329","documentation":"UnsupportedOperationException thrown by ElasticsearchNode.plugin(String pluginProjectPath) — the String-overload of plugin() is intentionally unsupported. The node only accepts plugin installs as Provider<RegularFile> (resolved file providers), because it needs concrete files rather than project-path references resolved later by Gradle.","triggerScenarios":"Calling testClusters.cluster.plugin('someProjectPath') or node.plugin('someProjectPath') — i.e. the String variant defined by the testclusters DSL interface but overridden to throw here.","commonSituations":"Copy-pasting plugin-install snippets from older ES versions or other testcluster implementations that accepted project paths; following the interface contract without noticing the override.","solutions":["Use the Provider<RegularFile> overload: `node.plugin(project.getLayout().getBuildDirectory().file('plugins/myplugin.zip'))`.","Install from a task output provider, e.g. `node.plugin(tasks.named('zipPlugin', Zip).map(t -> t.getArchiveFile().get())`.","Reference the supported plugin(Provider<RegularFile>) overload shown immediately above the throwing one."],"exampleFix":"// before\nnode.plugin(':my-plugins:foo')  // throws UnsupportedOperationException\n\n// after\nnode.plugin(project.provider(() -> project.file('build/plugins/foo.zip'))\n          .map(f -> project.getLayout().getProjectDirectory().file(f.getPath())))","handlingStrategy":"validation","validationCode":"// Resolve to a file provider before calling plugin()\nProvider<RegularFile> fileProvider = project.getLayout().getBuildDirectory().file(\"plugins/foo.zip\");\nnode.plugin(fileProvider);","typeGuard":"static boolean isSupportedPluginArg(Object arg) {\n    return arg instanceof Provider<?> p && (p.get() instanceof RegularFile || p.get() instanceof File);\n}","tryCatchPattern":null,"preventionTips":["Never call node.plugin(String); always pass a Provider<RegularFile>.","Wrap a TaskProvider's archive via .map(t -> t.getArchiveFile()).","Add a convention lint that flags String-based plugin/module calls."],"tags":["test","testclusters","api-misuse","plugin"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}