apache/druid · error · DruidException
must have an even number of arguments
Error message
must have an even number of arguments
What it means
Druid's JSON_OBJECT nested-data macro builds an object from alternating key/value arguments, so it requires an even argument count. Druid throws a validation failure at expression compilation when an odd number of arguments is passed, since at least one key would lack a value.
Source
Thrown at processing/src/main/java/org/apache/druid/query/expression/NestedDataExpressions.java:67
public class NestedDataExpressions
{
private static ExpressionType JSON_ARRAY = ExpressionTypeFactory.getInstance().ofArray(ExpressionType.NESTED_DATA);
public static class JsonObjectExprMacro implements ExprMacroTable.ExprMacro
{
public static final String NAME = "json_object";
@Override
public String name()
{
return NAME;
}
@Override
public Expr apply(List<Expr> args)
{
if (args.size() % 2 != 0) {
throw validationFailed("must have an even number of arguments");
}
class StructExpr extends ExprMacroTable.BaseScalarMacroFunctionExpr
{
public StructExpr(List<Expr> args)
{
super(JsonObjectExprMacro.this, args);
}
@Override
public ExprEval eval(ObjectBinding bindings)
{
HashMap<String, Object> theMap = new HashMap<>();
for (int i = 0; i < args.size(); i += 2) {
ExprEval field = args.get(i).eval(bindings);
ExprEval value = args.get(i + 1).eval(bindings);
if (!field.type().is(ExprType.STRING)) {View on GitHub (pinned to 9b90983fd2)
Solutions
- Count the arguments and add the missing key or value so pairs are complete: JSON_OBJECT('a', 1, 'b', 2).
- If a pair is not needed, remove both its key and value arguments.
- In generated SQL, assert args.size() % 2 == 0 before emitting the JSON_OBJECT call to fail early in your own code.
Example fix
-- before
SELECT JSON_OBJECT('a', x, 'b') FROM t
-- after
SELECT JSON_OBJECT('a', x, 'b', y) FROM t Defensive patterns
Strategy: validation
Validate before calling
// JS/TS before emitting SQL
if (pairs.length % 2 !== 0) throw new Error('JSON_OBJECT requires an even number of key/value arguments'); Type guard
function hasEvenArgs(args) { return Array.isArray(args) && args.length % 2 === 0; } Try / catch
try {
return runDruidQuery(query);
} catch (ExpressionValidationException e) {
if (e.getMessage().contains("even number of arguments")) {
throw new UserInputException("JSON_OBJECT arguments must come in key/value pairs");
}
throw e;
} Prevention
- Build JSON_OBJECT arguments from a Map/pairs array, joining keys and values, so parity is structural.
- Add an assertion (args.size() % 2 == 0) in query-generating code.
- Review SQL by hand after removing any key/value pair from JSON_OBJECT calls.
When it happens
Trigger: Calling JSON_OBJECT(k1, v1, k2) — any odd-sized argument list to the JSON_OBJECT expression macro in a Druid SQL query or native expression selector.
Common situations: Programmatic query builders that append a value but skip its key (or vice versa); hand-written SQL where a key/value pair was deleted or duplicated incompletely; refactoring that dropped a trailing argument.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Must provide at least one range
- Function[%s] %s
- Invalid expression: %s; %s used as both scalar and array var
- does not accept arguments
- requires 1 argument
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/8d2fa70cb7e85b31.
Report an issue: GitHub.