elastic/elasticsearch · error · InvalidUserDataException
invalid deploymentTarget '{}', expected one of {}
Error message
invalid deploymentTarget '{}', expected one of {} What it means
Thrown when deploymentTarget on an esplugin is not one of ALL, STATELESS_ONLY, STATEFUL_ONLY (the DEPLOYMENT_TARGETS set). Defaults to "ALL" when unset, so this only fires when explicitly set to an invalid value. deploymentTarget controls whether the plugin is loaded by stateful clusters, stateless clusters, or both.
Source
Thrown at build-tools/src/main/java/org/elasticsearch/gradle/plugin/GeneratePluginPropertiesTask.java:135
}
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());
String deploymentTarget = getDeploymentTarget().getOrElse("ALL");
if (DEPLOYMENT_TARGETS.contains(deploymentTarget) == false) {
throw new InvalidUserDataException(
"invalid deploymentTarget '" + deploymentTarget + "', expected one of " + DEPLOYMENT_TARGETS
);
}
props.put("deploymentTarget", deploymentTarget);
SimpleTemplateEngine engine = new SimpleTemplateEngine();
Path outputFile = getOutputFile().get().getAsFile().toPath();
Files.createDirectories(outputFile.getParent());
try (
var inputStream = GeneratePluginPropertiesTask.class.getResourceAsStream("/" + PROPERTIES_FILENAME);
var reader = new BufferedReader(new InputStreamReader(inputStream));
var writer = Files.newBufferedWriter(outputFile, StandardCharsets.UTF_8)
) {
Template template = engine.createTemplate(reader);
template.make(props).writeTo(writer);
}
}
View on GitHub (pinned to db6a809a66)
Solutions
- Set deploymentTarget to exactly one of: 'ALL', 'STATELESS_ONLY', 'STATEFUL_ONLY' (uppercase, with _ONLY suffix).
- If unsure, omit deploymentTarget entirely — it defaults to 'ALL' and the plugin loads everywhere.
- Re-check DEPLOYMENT_TARGETS in GeneratePluginPropertiesTask if you are on a fork that extended the set.
Example fix
// before
esplugin {
deploymentTarget = 'STATELESS'
}
// after
esplugin {
deploymentTarget = 'STATELESS_ONLY'
} Defensive patterns
Strategy: validation
Validate before calling
Set<String> allowed = Set.of("ALL", "STATELESS_ONLY", "STATEFUL_ONLY");
String target = deploymentTarget; // value to set
if (!allowed.contains(target)) {
throw new IllegalArgumentException("deploymentTarget must be one of " + allowed);
}
esplugin { deploymentTarget = target } Prevention
- Source deploymentTarget from an enum or constant rather than a raw string.
- Omit deploymentTarget when unsure — the default 'ALL' is safe.
- Cross-check against DEPLOYMENT_TARGETS in GeneratePluginPropertiesTask on branch upgrades.
When it happens
Trigger: esplugin { deploymentTarget = 'STATELESS' } (missing _ONLY suffix), or any typo / case variation. The guard runs late in generatePropertiesFile after getDeploymentTarget().getOrElse("ALL").
Common situations: Migrating a plugin to support stateless mode and guessing the enum value, or using a value from an older/newer branch where the constant set differs.
Related errors
- classname is a required setting for esplugin
- classname is a forbidden for stable esplugin
- 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/067e4c47e9d9dc5c.
Report an issue: GitHub.