apache/druid · error · ParseException

Cannot coerce column [%s] input to requested type [%s]

Error message

Cannot coerce column [%s] input to requested type [%s]

What it means

During auto (nested JSON) column indexing, the value read from a row is cast to the column's configured castToExpressionType. If ExprEval.castTo cannot coerce the input value (e.g. casting a non-numeric string to LONG), it throws IllegalArgumentException, which this code wraps in a Druid ParseException naming the column and requested type. This indicates ingested data does not match the declared type of the auto-type column.

Source

Thrown at processing/src/main/java/org/apache/druid/segment/AutoTypeColumnIndexer.java:180

    } else {
      return processAuto(dimValues);
    }
  }

  /**
   * Process values which will all be cast to {@link #castToExpressionType}. This method should not be used for
   * and does not handle actual nested data structures, use {@link #processAuto(Object)} instead.
   */
  private EncodedKeyComponent<StructuredData> processCast(@Nullable Object dimValues)
  {
    final long oldDictSizeInBytes = globalDictionary.sizeInBytes();
    final int oldFieldKeySize = estimatedFieldKeySize;
    ExprEval<?> eval = ExprEval.bestEffortOf(dimValues);
    try {
      eval = eval.castTo(castToExpressionType);
    }
    catch (IAE invalidCast) {
      throw new ParseException(eval.asString(), invalidCast, "Cannot coerce column [%s] input to requested type [%s]", columnName, castToType);
    }

    FieldIndexer fieldIndexer = fieldIndexers.get(NestedPathFinder.JSON_PATH_ROOT);
    if (fieldIndexer == null) {
      estimatedFieldKeySize += StructuredDataProcessor.estimateStringSize(NestedPathFinder.JSON_PATH_ROOT);
      fieldIndexer = new FieldIndexer(globalDictionary);
      fieldIndexers.put(NestedPathFinder.JSON_PATH_ROOT, fieldIndexer);
    }
    StructuredDataProcessor.ProcessedValue<?> rootValue = fieldIndexer.processValue(eval);
    long effectiveSizeBytes = rootValue.getSize();
    // then, we add the delta of size change to the global dictionaries to account for any new space added by the
    // 'raw' data
    effectiveSizeBytes += (globalDictionary.sizeInBytes() - oldDictSizeInBytes);
    effectiveSizeBytes += (estimatedFieldKeySize - oldFieldKeySize);
    return new EncodedKeyComponent<>(StructuredData.wrap(eval.value()), effectiveSizeBytes);
  }

  /**

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Fix or filter the offending input value so it matches the target type before ingestion (clean the record, or drop/transform the field).
  2. Use an input-format transform or expression to sanitize values (e.g. TRY_CAST-like handling) so castTo succeeds.
  3. If values are legitimately non-numeric, remove the cast / let auto-type detection keep them as STRING.
  4. Inspect the message's column name and the input string in the ParseException to locate and repair the bad record.

Example fix

// before: direct cast of raw string values to LONG fails on 'N/A'
"dimensionExclusions": [], "useSchemaDiscovery": true
// after: transform bad values before cast
"transforms": [{"type": "expression", "name": "amount",
  "expression": "if(lookup(amount, 'na-map') == null, amount, null)"}]
Defensive patterns

Strategy: validation

Validate before calling

Object v = row.get(column);
if (v instanceof String && target == ColumnType.LONG
    && !v.toString().matches("-?\\d+(\\.\\d+)?")) {
  throw new IllegalArgumentException("value not castable to LONG: " + v);
}

Type guard

boolean castable(String s, ColumnType t) {
  switch (t.getType()) {
    case LONG: return s.matches("-?\\d+");
    case DOUBLE: return s.matches("-?\\d+(\\.\\d+)?(E-?\\d+)?");
    default: return true;
  }
}

Try / catch

try {
  indexer.processRowValsToUnsortedEncodedKeyComponent(vals, rowId, castToType);
} catch (ParseException pe) {
  log.error(pe, "bad value for column %s", pe.getCause());
  metrics.incrementRowOutputCountOfFailure();
}

Prevention

When it happens

Trigger: Ingesting rows into an auto/NESTED_DATA column with a configured type cast (e.g. via auto-type detection or a dimension schema entry with type cast) where a value cannot be coerced — e.g. string 'abc' cast to LONG, or an object cast to a scalar type.

Common situations: Dirty input data in batch/stream ingestion; a user adds a typed dimension spec to an existing JSON column whose values are heterogeneous; changing a column's declared type after data was written with incompatible values.

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/35aa0680006d0cc5. Report an issue: GitHub.