apache/druid · error · DruidException

Cannot coerce value [ ] of type [ ] for column [ ] to

Error message

Cannot coerce value [%s] of type [%s] for column [%s] to %s

What it means

ClusterGroupTuples.coerceValue canonicalizes clustering-column tuple values to their declared ColumnType so equality works across the JSON/programmatic boundary. For LONG columns it only accepts Number instances and calls longValue(); anything else (String, Boolean, etc.) triggers InvalidInput 'Cannot coerce value ... to LONG'. Strings are deliberately not parsed to avoid silently accepting operator typos.

Solutions

  1. Change the tuple value to a JSON number for LONG columns: use 42 not "42"
  2. Fix the rule/JSON authoring tool to emit typed numbers instead of strings
  3. If values truly are numeric strings, parse them at authoring time (e.g. Long.parseLong) before constructing ClusterGroupTuples; the library intentionally will not parse them

Example fix

// before (rule JSON)
{"tuples": [["1000"]]}
// after
{"tuples": [[1000]]}
Defensive patterns

Strategy: validation

Validate before calling

Object v = tuple.get(i);
if (v != null && "LONG".equals(declaredType) && !(v instanceof Number)) {
  throw new IllegalArgumentException(
      "Column " + name + " expects a JSON number (LONG), got: " + v.getClass().getSimpleName());
}

Type guard

boolean isTypedNumber(Object v) {
  return v instanceof Number;
}

Try / catch

try {
  ClusterGroupTuples ct = new ClusterGroupTuples(signature, virtualColumns, tuples);
} catch (InvalidInput e) {
  if (e.getMessage() != null && e.getMessage().contains("Cannot coerce value")) {
    log.error("Rule tuple has wrong JSON type (quoted number?); fix to numeric literal");
    return null; // treat as no-match per documented rule-matcher guidance
  }
  throw e;
}

Prevention

When it happens

Trigger: Constructing ClusterGroupTuples (via constructor or Jackson deserialization) whose tuple value for a LONG clustering column is a non-Number, e.g. a JSON string "42" or boolean where a numeric JSON value 42 is required; canonicalizeTuples calls coerceValue and throws.

Common situations: Hand-authored partial-load rule JSON with quoted numbers ("42" instead of 42); rule files produced by tools that stringify values; clustering columns declared LONG in the segment signature but rule tuples authored as strings.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/timeline/ClusterGroupTuples.java:107

   *   <li>{@link ClusterGroupTuples}'s compact constructor to canonicalize segment-side tuples (strict).</li>
   *   <li>Operator-supplied rule tuples in future cluster-group partial-load matchers, which can catch the
   *       exception and treat it as "no match for this segment" rather than a hard failure.</li>
   * </ul>
   */
  @Nullable
  public static Object coerceValue(String columnName, ColumnType type, @Nullable Object raw)
  {
    if (raw == null) {
      return null;
    }
    if (ColumnType.STRING.equals(type)) {
      return raw instanceof String ? raw : Objects.toString(raw);
    }
    if (ColumnType.LONG.equals(type)) {
      if (raw instanceof Number) {
        return ((Number) raw).longValue();
      }
      throw cannotCoerce(raw, columnName, "LONG");
    }
    if (ColumnType.DOUBLE.equals(type)) {
      if (raw instanceof Number) {
        return ((Number) raw).doubleValue();
      }
      throw cannotCoerce(raw, columnName, "DOUBLE");
    }
    if (ColumnType.FLOAT.equals(type)) {
      if (raw instanceof Number) {
        return ((Number) raw).floatValue();
      }
      throw cannotCoerce(raw, columnName, "FLOAT");
    }
    throw InvalidInput.exception(
        "Unsupported clustering column type [%s] for column [%s]; supported types are STRING, LONG, DOUBLE, FLOAT",
        type,
        columnName
    );

View on GitHub (pinned to 9b90983fd2)