apache/druid · error · org.apache.druid.java.util.common.parsers.ParseException

Unable to parse value[%s] for field[%s]

Error message

Unable to parse value[%s] for field[%s]

What it means

When the field value is a String, objectToNumber strips commas and a leading '+', then tries Longs.tryParse followed by Double.valueOf. If both fail, the string is not a valid number. With throwParseExceptions=true it throws a Druid ParseException naming the offending value and field; otherwise it silently returns null. This lets ingestion/queries fail fast (or skip) on non-numeric string data.

Source

Thrown at processing/src/main/java/org/apache/druid/data/input/Rows.java:153

        metricValueString = trimLeadingPlusOfLongString(metricValueString);

        Number v = null;

        // Try parsing as Long first, since it's significantly faster than Double parsing, and also there are various
        // integer numbers that can be represented as Long but cannot be represented as Double.
        if (outputType == null || outputType == ValueType.LONG) {
          v = Longs.tryParse(metricValueString);
        }

        if (v == null) {
          v = Double.valueOf(metricValueString);
        }

        asNumber = v;
      }
      catch (Exception e) {
        if (throwParseExceptions) {
          throw new ParseException(
              String.valueOf(inputValue),
              e,
              "Unable to parse value[%s] for field[%s]",
              inputValue,
              name
          );
        } else {
          return null;
        }
      }
    } else {
      if (throwParseExceptions) {
        throw new ParseException(
            String.valueOf(inputValue),
            "Unknown type[%s] for field[%s]",
            inputValue.getClass(),
            name
        );

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Fix the input data so the string is a plain numeric literal (e.g. "12.3" not "12.3.4").
  2. Set throwParseExceptions=false so unparseable values become null instead of failing the row.
  3. Remove thousands separators and currency/locale formatting upstream before ingestion.
  4. Change the column's type spec to STRING if the data is genuinely non-numeric.

Example fix

// before
Number n = Rows.objectToNumber("revenue", "1,234.5a", true);
// after
Number n = Rows.objectToNumber("revenue", "1234.5", true);
Defensive patterns

Strategy: validation

Validate before calling

boolean isNumericString(String s) {
  String t = s == null ? "" : s.replace(",", "").trim();
  return com.google.common.primitives.Longs.tryParse(t) != null || parseDoubleSafe(t) != null;
}

Type guard

Number asNumberIfPossible(Object v) {
  return v instanceof Number ? (Number) v
      : (v instanceof String && isNumericString((String) v)) ? Rows.objectToNumber("f", v, false) : null;
}

Try / catch

try {
  return Rows.objectToNumber(field, value, true);
} catch (ParseException e) {
  log.warn("Non-numeric value for field %s: %s", field, value);
  return null; // or route to a dead-letter path
}

Prevention

When it happens

Trigger: Passing a String like "abc", "12.3.4", empty string after trim, or a value with thousands separators beyond Druid's comma handling into Rows.objectToNumber with throwParseExceptions=true and the string neither parseable as Long nor Double.

Common situations: CSV/TSV ingestion with a malformed metric column; user-supplied query filters or virtual columns referencing a string dimension as if numeric; locale-formatted numbers such as "1.234,56" or values containing currency symbols; JSON ingestion where a field is quoted but expected numeric.

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