apache/druid · error · IllegalArgumentException
druid.indexer.runner.javaOptsArray in context of task: X…
Error message
druid.indexer.runner.javaOptsArray in context of task: X must be an array of strings.
What it means
ForkingTaskRunner allows a task to override the middle manager's Java options via the 'druid.indexer.runner.javaOptsArray' context key. That context value must be an array of strings; if reading/iterating it fails, the runner wraps the cause in IllegalArgumentException naming the task.
Solutions
- Set druid.indexer.runner.javaOptsArray to a JSON array of strings, e.g. ["-Xmx2g","-XX:+UseG1GC"].
- If you want a single string, use druid.indexer.runner.javaOpts instead of javaOptsArray.
- Ensure every element is a string; avoid numeric/boolean entries.
Example fix
// before
"context": {"druid.indexer.runner.javaOptsArray": "-Xmx2g -XX:+UseG1GC"}
// after
"context": {"druid.indexer.runner.javaOptsArray": ["-Xmx2g", "-XX:+UseG1GC"]} Defensive patterns
Strategy: validation
Validate before calling
Object opts = task.getContextValue("druid.indexer.runner.javaOptsArray");
if (opts != null && !(opts instanceof List
&& ((List<?>) opts).stream().allMatch(o -> o instanceof String))) {
throw new IllegalArgumentException("javaOptsArray must be an array of strings");
} Try / catch
try {
submitTask(task);
} catch (IllegalArgumentException e) {
// fix context druid.indexer.runner.javaOptsArray to List<String>
} Prevention
- Use javaOptsArray only with JSON arrays like ["-Xmx2g"]; use javaOpts for single strings.
- Add a client-side schema check on the task context before submission.
- Avoid copying javaOpts values into javaOptsArray without splitting.
When it happens
Trigger: Submitting a task whose context contains druid.indexer.runner.javaOptsArray as a non-array (string, object, number) or an array containing non-string elements; the failure occurs while building the fork command in ForkingTaskRunner.call.
Common situations: Copying a single-string javaOpts value into javaOptsArray without splitting; JSON quoting mistakes in the task context; programmatic builders putting non-string objects into context.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Cannot simultaneously replace and append to existing…
- Conflicting segment granularities found
- Failed to parse metric dimensions and types
- Interval[ ] is empty, must specify a nonempty interval
- Invalid maxLoadFactor
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/fc2adb9a2674929b.
Report an issue: GitHub.
Appendix: source
Thrown at indexing-service/src/main/java/org/apache/druid/indexing/overlord/ForkingTaskRunner.java:287
Object taskJavaOpts = task.getContextValue(
ForkingTaskRunnerConfig.JAVA_OPTS_PROPERTY
);
if (taskJavaOpts != null) {
command.addAll(new QuotableWhiteSpaceSplitter((String) taskJavaOpts));
}
// Override task specific javaOptsArray
try {
List<String> taskJavaOptsArray = jsonMapper.convertValue(
task.getContextValue(ForkingTaskRunnerConfig.JAVA_OPTS_ARRAY_PROPERTY),
new TypeReference<>() {}
);
if (taskJavaOptsArray != null) {
command.addAll(taskJavaOptsArray);
}
}
catch (Exception e) {
throw new IllegalArgumentException(
ForkingTaskRunnerConfig.JAVA_OPTS_ARRAY_PROPERTY
+ " in context of task: " + task.getId() + " must be an array of strings.",
e
);
}
for (String propName : props.stringPropertyNames()) {
for (String allowedPrefix : config.getAllowedPrefixes()) {
// See https://github.com/apache/druid/issues/1841
if (propName.startsWith(allowedPrefix)
&& !ForkingTaskRunnerConfig.JAVA_OPTS_PROPERTY.equals(propName)
&& !ForkingTaskRunnerConfig.JAVA_OPTS_ARRAY_PROPERTY.equals(propName)
) {
command.addSystemProperty(propName, props.getProperty(propName));
}
}
}
View on GitHub (pinned to 9b90983fd2)