{"record":{"id":"35aa0680006d0cc5","repo":"apache/druid","slug":"cannot-coerce-column-s-input-to-requested-type","errorCode":null,"errorMessage":"Cannot coerce column [%s] input to requested type [%s]","messagePattern":"Cannot coerce column \\[(.+?)\\] input to requested type \\[(.+?)\\]","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/AutoTypeColumnIndexer.java","lineNumber":180,"sourceCode":"    } else {\n      return processAuto(dimValues);\n    }\n  }\n\n  /**\n   * Process values which will all be cast to {@link #castToExpressionType}. This method should not be used for\n   * and does not handle actual nested data structures, use {@link #processAuto(Object)} instead.\n   */\n  private EncodedKeyComponent<StructuredData> processCast(@Nullable Object dimValues)\n  {\n    final long oldDictSizeInBytes = globalDictionary.sizeInBytes();\n    final int oldFieldKeySize = estimatedFieldKeySize;\n    ExprEval<?> eval = ExprEval.bestEffortOf(dimValues);\n    try {\n      eval = eval.castTo(castToExpressionType);\n    }\n    catch (IAE invalidCast) {\n      throw new ParseException(eval.asString(), invalidCast, \"Cannot coerce column [%s] input to requested type [%s]\", columnName, castToType);\n    }\n\n    FieldIndexer fieldIndexer = fieldIndexers.get(NestedPathFinder.JSON_PATH_ROOT);\n    if (fieldIndexer == null) {\n      estimatedFieldKeySize += StructuredDataProcessor.estimateStringSize(NestedPathFinder.JSON_PATH_ROOT);\n      fieldIndexer = new FieldIndexer(globalDictionary);\n      fieldIndexers.put(NestedPathFinder.JSON_PATH_ROOT, fieldIndexer);\n    }\n    StructuredDataProcessor.ProcessedValue<?> rootValue = fieldIndexer.processValue(eval);\n    long effectiveSizeBytes = rootValue.getSize();\n    // then, we add the delta of size change to the global dictionaries to account for any new space added by the\n    // 'raw' data\n    effectiveSizeBytes += (globalDictionary.sizeInBytes() - oldDictSizeInBytes);\n    effectiveSizeBytes += (estimatedFieldKeySize - oldFieldKeySize);\n    return new EncodedKeyComponent<>(StructuredData.wrap(eval.value()), effectiveSizeBytes);\n  }\n\n  /**","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/AutoTypeColumnIndexer.java#L162-L198","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix or filter the offending input value so it matches the target type before ingestion (clean the record, or drop/transform the field).","Use an input-format transform or expression to sanitize values (e.g. TRY_CAST-like handling) so castTo succeeds.","If values are legitimately non-numeric, remove the cast / let auto-type detection keep them as STRING.","Inspect the message's column name and the input string in the ParseException to locate and repair the bad record."],"exampleFix":"// before: direct cast of raw string values to LONG fails on 'N/A'\n\"dimensionExclusions\": [], \"useSchemaDiscovery\": true\n// after: transform bad values before cast\n\"transforms\": [{\"type\": \"expression\", \"name\": \"amount\",\n  \"expression\": \"if(lookup(amount, 'na-map') == null, amount, null)\"}]","handlingStrategy":"validation","validationCode":"Object v = row.get(column);\nif (v instanceof String && target == ColumnType.LONG\n    && !v.toString().matches(\"-?\\\\d+(\\\\.\\\\d+)?\")) {\n  throw new IllegalArgumentException(\"value not castable to LONG: \" + v);\n}","typeGuard":"boolean castable(String s, ColumnType t) {\n  switch (t.getType()) {\n    case LONG: return s.matches(\"-?\\\\d+\");\n    case DOUBLE: return s.matches(\"-?\\\\d+(\\\\.\\\\d+)?(E-?\\\\d+)?\");\n    default: return true;\n  }\n}","tryCatchPattern":"try {\n  indexer.processRowValsToUnsortedEncodedKeyComponent(vals, rowId, castToType);\n} catch (ParseException pe) {\n  log.error(pe, \"bad value for column %s\", pe.getCause());\n  metrics.incrementRowOutputCountOfFailure();\n}","preventionTips":["Validate input data against the declared column type before ingestion","Add transforms to sanitize/normalize messy fields","Avoid casting heterogeneous JSON fields without checks","Monitor ParseException rates in ingestion metrics"],"tags":["java","ingestion","nested-columns","type-cast","parse-error"],"backgroundTag":"type-mismatch","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}