apache/druid · error · RE

Failed to parse array element

Error message

Failed to parse array element %s as a string

What it means

Thrown while parsing an explicit ARRAY<STRING> literal when an element is not NULL, STRING, DOUBLE, or LONG — i.e. a bare identifier or other token cannot be treated as a string element. Unlike the typed-string-array path, numbers are coerced to their text, but non-literals are rejected.

Solutions

  1. Quote the offending element as a string literal
  2. Remove the non-literal element or replace it with a valid string
  3. Ensure the expression generator escapes and quotes string values

Example fix

// before
ARRAY<STRING>[abc, 'def']
// after
ARRAY<STRING>['abc', 'def']
Defensive patterns

Strategy: validation

Validate before calling

// Java: require quoted strings (or coercible numerics/NULL) for ARRAY<STRING>
static boolean isValidExplicitStringArrayElement(String e) {
  return e.equals("NULL")
      || (e.startsWith("'") && e.endsWith("'"))
      || e.matches("-?\\d+(\\.\\d+)?([eE][-?+]?\\d+)?");
}

Prevention

When it happens

Trigger: Parsing ARRAY<STRING>[foo,bar] where elements are unquoted identifiers rather than quoted strings or numeric literals.

Common situations: Generated expressions that forget to quote strings; mixing boolean/identifier tokens into string arrays; hand-written filters with unquoted values.

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


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/8be329f4f07a283d. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/math/expr/ExprListenerImpl.java:511

    }
    nodes.put(ctx, new ArrayExpr(ExpressionType.STRING_ARRAY, values));
  }

  @Override
  public void exitExplicitStringArray(ExprParser.ExplicitStringArrayContext ctx)
  {
    Object[] values = new Object[ctx.literalElement().size()];
    for (int i = 0; i < values.length; i++) {
      if (ctx.literalElement(i).NULL() != null) {
        values[i] = null;
      } else if (ctx.literalElement(i).STRING() != null) {
        values[i] = escapeStringLiteral(ctx.literalElement(i).STRING().getText());
      } else if (ctx.literalElement(i).DOUBLE() != null) {
        values[i] = ctx.literalElement(i).DOUBLE().getText();
      } else if (ctx.literalElement(i).LONG() != null) {
        values[i] = ctx.literalElement(i).LONG().getText();
      } else {
        throw new RE("Failed to parse array element %s as a string", ctx.literalElement(i).getText());
      }
    }
    nodes.put(ctx, new ArrayExpr(ExpressionType.STRING_ARRAY, values));
  }

  /**
   * All {@link IdentifierExpr} that are *not* bound to a {@link LambdaExpr} identifier, will recieve a unique
   * {@link IdentifierExpr#identifier} value which may or may not be the same as the
   * {@link IdentifierExpr#binding} value. {@link LambdaExpr} identifiers however, will always have
   * {@link IdentifierExpr#identifier} be the same as {@link IdentifierExpr#binding} because they have
   * synthetic bindings set at evaluation time. This is done to aid in analysis needed for the automatic expression
   * translation which maps scalar expressions to multi-value inputs. See
   * {@link Parser#applyUnappliedBindings(Expr, Expr.BindingAnalysis, List)}} for additional details.
   */
  private IdentifierExpr createIdentifierExpr(String binding)
  {
    if (!lambdaIdentifiers.contains(binding)) {
      String uniqueIdentifier = binding;

View on GitHub (pinned to 9b90983fd2)