{"record":{"id":"1c7ea93bc5922dee","repo":"elastic/elasticsearch","slug":"reaperplugin-can-only-be-applied-to-the-root-proje","errorCode":null,"errorMessage":"ReaperPlugin can only be applied to the root project of a build","messagePattern":"ReaperPlugin can only be applied to the root project of a build","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"build-tools/src/main/java/org/elasticsearch/gradle/ReaperPlugin.java","lineNumber":43,"sourceCode":"    /**\n     * The unique identifier to register the reaper shared service within a gradle build\n     * */\n    public static final String REAPER_SERVICE_NAME = \"reaper\";\n    private final ProjectLayout projectLayout;\n\n    @Inject\n    ReaperPlugin(ProjectLayout projectLayout) {\n        this.projectLayout = projectLayout;\n    }\n\n    @Override\n    public void apply(Project project) {\n        registerReaperService(project, projectLayout, false);\n    }\n\n    public static void registerReaperService(Project project, ProjectLayout projectLayout, boolean internal) {\n        if (project != project.getRootProject()) {\n            throw new IllegalArgumentException(\"ReaperPlugin can only be applied to the root project of a build\");\n        }\n        File inputDir = projectLayout.getProjectDirectory()\n            .dir(\".gradle\")\n            .dir(\"reaper\")\n            .dir(\"build-\" + ProcessHandle.current().pid())\n            .getAsFile();\n\n        project.getGradle().getSharedServices().registerIfAbsent(REAPER_SERVICE_NAME, ReaperService.class, spec -> {\n            // Provide some parameters\n            spec.getParameters().getInputDir().set(inputDir);\n            spec.getParameters().getBuildDir().set(projectLayout.getBuildDirectory());\n            spec.getParameters().setInternal(internal);\n        });\n    }\n\n}\n","sourceCodeStart":25,"sourceCodeEnd":60,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools/src/main/java/org/elasticsearch/gradle/ReaperPlugin.java#L25-L60","documentation":"ReaperPlugin.registerReaperService() throws IllegalArgumentException when the project it is applied to is not the root project. The reaper is a Gradle BuildService registered via registerIfAbsent with a fixed name; it must be a build-wide singleton to track all spawned processes across subprojects. Applying it to a subproject would either duplicate the service or scope it incorrectly.","triggerScenarios":"Applying the reaper plugin (`apply plugin: 'elasticsearch.reaper'`) in a subproject's build.gradle, or calling ReaperPlugin.registerReaperService(subproject, ...) directly from build logic in a child project.","commonSituations":"Copy-pasting a plugin block from a root build.gradle into a submodule; a subproject that spawns external processes wanting its own reaper; misconfigured composite builds where the plugin is applied at the wrong level.","solutions":["Apply ReaperPlugin only in the root project's build.gradle (or settings.gradle applied to the root).","If subprojects need the reaper, register it once at the root and have subprojects consume the shared service by name.","Use registerReaperService(project.rootProject, ...) to redirect the call to the root if invoked from a subproject context."],"exampleFix":"// before (in submodule build.gradle)\napply plugin: 'elasticsearch.reaper' // throws\n\n// after (in root build.gradle)\napply plugin: 'elasticsearch.reaper'","handlingStrategy":"validation","validationCode":"if (project != project.getRootProject()) {\n    throw new IllegalArgumentException(\"Apply ReaperPlugin only to the root project\");\n}\nReaperPlugin.registerReaperService(project, projectLayout, internal);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Apply ReaperPlugin in the root build.gradle only.","Subprojects should consume the root-registered service by name, not re-apply the plugin.","Use project.getRootProject() to redirect registration if called from a subproject."],"tags":["gradle","build-tools","reaper","configuration-validation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}