elastic/elasticsearch · error · InvalidUserDataException
classname is a required setting for esplugin
Error message
classname is a required setting for esplugin
What it means
Thrown by GeneratePluginPropertiesTask.generatePropertiesFile when an esplugin declaration omits classname and the plugin is NOT marked stable. The task needs a plugin entry-point class name to emit into plugin-descriptor.properties, so a non-stable plugin without one is misconfigured.
Source
Thrown at build-tools/src/main/java/org/elasticsearch/gradle/plugin/GeneratePluginPropertiesTask.java:113
@PathSensitive(PathSensitivity.RELATIVE)
public abstract ConfigurableFileCollection getModuleInfoFile();
@OutputFile
public abstract RegularFileProperty getOutputFile();
@Input
public abstract Property<Boolean> getIsStable();
@Input
@Optional
public abstract Property<String> getDeploymentTarget();
@TaskAction
public void generatePropertiesFile() throws IOException {
String classname = getClassname().getOrElse("");
boolean stablePlugin = getIsStable().getOrElse(false);
if (stablePlugin == false && classname.isEmpty()) {
throw new InvalidUserDataException("classname is a required setting for esplugin");
}
if (stablePlugin && classname.isEmpty() == false) {
throw new InvalidUserDataException("classname is a forbidden for stable esplugin");
}
Map<String, Object> props = new HashMap<>();
props.put("name", getPluginName().get());
props.put("description", getPluginDescription().get());
props.put("version", getPluginVersion().get());
props.put("elasticsearchVersion", getElasticsearchVersion().get());
props.put("javaVersion", getJavaVersion().get());
props.put("classname", classname);
props.put("extendedPlugins", String.join(",", getExtendedPlugins().get()));
props.put("hasNativeController", getHasNativeController().get());
props.put("nativeControllerEnabledSettings", String.join(",", getNativeControllerEnabledSettings().get()));
props.put("requiresKeystore", getRequiresKeystore().get());
props.put("licensed", getIsLicensed().get());
props.put("modulename", findModuleName());View on GitHub (pinned to db6a809a66)
Solutions
- Add `classname '<fully.qualified.PluginClass>'` to the esplugin { } block, pointing at a class extending org.elasticsearch.plugins.Plugin.
- If the module is a stable plugin (no real Plugin class), set `isStable = true` instead so classname is intentionally omitted (see error 42 for the inverse rule).
- Verify the referenced class exists in the project's main source set and compiles.
Example fix
// before
esplugin {
name 'my-plugin'
description '...'
// classname missing
}
// after
esplugin {
name 'my-plugin'
description '...'
classname 'com.acme.MyPlugin'
} Defensive patterns
Strategy: validation
Validate before calling
// In a Gradle init script or convention plugin, validate before the task runs
project.tasks.withType(GeneratePluginPropertiesTask.class).configureEach {
if (!it.isStable.get() && it.classname.getOrElse('').trim().isEmpty()) {
throw new GradleException("esplugin '${it.pluginName.get()}' must set classname (or set isStable=true)")
}
} Prevention
- Treat classname and isStable as mutually exclusive toggles and lint for it in a convention plugin.
- When scaffolding a new plugin, template the esplugin block with classname pre-filled.
- Run generatePluginPropertiesTask early in CI to catch misconfiguration before the heavier build.
When it happens
Trigger: A Gradle project applies the esplugin plugin and calls esplugin { ... } without setting classname, while isStable defaults to false. The task runs at generation time (the generatePropertiesFile @TaskAction).
Common situations: Authoring a new Elasticsearch plugin and forgetting the `classname 'com.acme.FooPlugin'` line, or renaming/removing the Plugin subclass without updating the esplugin block.
Related errors
- classname is a forbidden for stable esplugin
- invalid deploymentTarget '{}', expected one of {}
- unrecognized classpath entry: {}
- Number of nodes should be >= 1 but was {} for {}
- Cannot shrink {} to have {} nodes as it already has {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/3c09430717af5642.
Report an issue: GitHub.