apache/druid · error · IllegalStateException

Unknown type [%s]

Error message

Unknown type [%s]

What it means

Numbers.parseLong only accepts String and Number inputs; any other non-null object type is unsupported and triggers ISE "Unknown type [class ...]". The exception reports the value's actual class so the caller can see which unexpected type arrived.

Source

Thrown at processing/src/main/java/org/apache/druid/java/util/common/Numbers.java:49

   * Parse the given object as a {@code long}. The input object can be a {@link String} or one of the implementations of
   * {@link Number}. You may want to use {@code GuavaUtils.tryParseLong()} instead if the input is a nullable string and
   * you want to avoid any exceptions.
   *
   * @throws NumberFormatException if the input is an unparseable string.
   * @throws NullPointerException if the input is null.
   * @throws ISE if the input is not a string or a number.
   */
  public static long parseLong(Object val)
  {
    if (val instanceof String) {
      return Long.parseLong((String) val);
    } else if (val instanceof Number) {
      return ((Number) val).longValue();
    } else {
      if (val == null) {
        throw new NullPointerException("Input is null");
      } else {
        throw new ISE("Unknown type [%s]", val.getClass());
      }
    }
  }

  /**
   * Parse the given object as a {@code int}. The input object can be a {@link String} or one of the implementations of
   * {@link Number}.
   *
   * @throws NumberFormatException if the input is an unparseable string.
   * @throws NullPointerException if the input is null.
   * @throws ISE if the input is not a string or a number.
   */
  public static int parseInt(Object val)
  {
    if (val instanceof String) {
      return Integer.parseInt((String) val);
    } else if (val instanceof Number) {
      return ((Number) val).intValue();

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Coerce the value to String or Number before calling (e.g. String.valueOf(val) or ((Date) val).getTime())
  2. Fix the upstream producer so the field is emitted as a number or numeric string
  3. Add a type check/dispatch before parsing for heterogeneous inputs
  4. Use a richer conversion utility (e.g. Jackson ObjectMapper.convertValue) that handles more types

Example fix

// before
long n = Numbers.parseLong(row.get("flag")); // row value is Boolean
// after
Object v = row.get("flag");
long n = v instanceof Boolean ? ((Boolean) v ? 1L : 0L) : Numbers.parseLong(v);
Defensive patterns

Strategy: type-guard

Validate before calling

if (val != null && !(val instanceof String) && !(val instanceof Number)) {
  throw new IllegalArgumentException("Expected String or Number, got " + val.getClass().getName());
}

Type guard

static boolean isParseableAsLong(Object val) {
  return val instanceof String || val instanceof Number;
}

Try / catch

try {
  return Numbers.parseLong(val);
} catch (IllegalStateException e) {
  log.warn("Unsupported type for parseLong: {}", val == null ? null : val.getClass());
  return fallbackConversion(val);
}

Prevention

When it happens

Trigger: Calling Numbers.parseLong with a non-null object that is neither String nor Number, e.g. a Boolean, Date, byte[], List, or a custom POJO obtained from a generic map.

Common situations: JSON booleans or arrays landing in a field expected to be numeric; timestamp values as Date objects from upstream deserialization; mixed-type columns in generic Map-based rows.

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