apache/druid · error · BadQueryContextException
Expected key [%s] to be CSV or JSON array, but got [%s]
Error message
Expected key [%s] to be CSV or JSON array, but got [%s]
What it means
Query context key parsing in MultiStageQueryContext expects a value that is either a comma-separated string or a JSON array string. When Jackson fails to parse the string as a JSON array (JsonProcessingException) in the JSON branch, Druid throws QueryContexts.badValueException stating the key must be a CSV or JSON array. This is a query-context validation error, so the query is rejected before execution.
Source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/util/MultiStageQueryContext.java:720
return queryContext.getInt(CTX_SEGMENT_LOAD_AHEAD_COUNT);
}
/**
* Decodes a list from either a JSON or CSV string.
*/
@VisibleForTesting
static List<String> decodeList(final String keyName, @Nullable final String listString)
{
if (listString == null) {
return Collections.emptyList();
} else if (LOOKS_LIKE_JSON_ARRAY.matcher(listString).matches()) {
try {
// Not caching this ObjectMapper in a static, because we expect to use it infrequently (once per INSERT
// query that uses this feature) and there is no need to keep it around longer than that.
return new ObjectMapper().readValue(listString, new TypeReference<>() {});
}
catch (JsonProcessingException e) {
throw QueryContexts.badValueException(keyName, "CSV or JSON array", listString);
}
} else {
final RFC4180Parser csvParser = new RFC4180ParserBuilder().withSeparator(',').build();
try {
return Arrays.stream(csvParser.parseLine(listString))
.filter(s -> s != null && !s.isEmpty())
.map(String::trim)
.collect(Collectors.toList());
}
catch (IOException e) {
throw QueryContexts.badValueException(keyName, "CSV or JSON array", listString);
}
}
}
/**
* Decodes {@link #CTX_INDEX_SPEC} from either a JSON-encoded string, or POJOs.View on GitHub (pinned to 9b90983fd2)
Solutions
- Pass the value as a simple comma-separated CSV string instead, e.g. "a,b,c", which avoids the JSON parser entirely.
- If using JSON, ensure it is a valid JSON array literal with double quotes: ["a","b"] with no trailing commas or single quotes.
- Verify the client is not double-encoding the value (a string containing escaped quotes like \" indicates double encoding).
Example fix
// before
queryContext.put("partitionKeys", "[\"country\", 'region]");
// after
queryContext.put("partitionKeys", "country,region"); Defensive patterns
Strategy: validation
Validate before calling
String v = (String) queryContext.get("myListKey");
if (v != null && v.trim().startsWith("[")) {
try { new ObjectMapper().readValue(v, List.class); }
catch (JsonProcessingException e) { throw new IllegalArgumentException("key must be CSV or a valid JSON array: " + v); }
} Prevention
- Prefer plain CSV strings ("a,b,c") for list-valued MSQ context keys.
- Never single-quote or trailing-comma JSON arrays in context values.
- Beware client double-encoding of JSON strings in HTTP/SQL clients.
When it happens
Trigger: Calling MultiStageQueryContext.getListStringFromContext-style parsing (e.g. for CTX_TASK_STORAGE_DIR or partitioning keys) with a query context value like '{"a":1}' or a malformed JSON string such as '["a", ' that is not valid JSON, in the branch where the value is treated as JSON rather than CSV.
Common situations: Users pass the context value as JSON via a client that double-encodes or single-quotes strings (e.g. '["a","b"]' with unescaped quotes), or a BI tool submits the context key as an object rather than a JSON-encoded string.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- No such outputChannelMode[%s]
- Must provide at least one range
- Expected key [indexSpec] to be an indexSpec, but got [%s]
- Failed to parse metric dimensions and types
- Unknown
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/a5be68e6d6a0a302.
Report an issue: GitHub.