apache/druid · error · BadQueryContextException

Expected key [%s] to be in integer format, but got [%s]

Error message

Expected key [%s] to be in integer format, but got [%s]

What it means

QueryContexts.getAsInt(key, value) throws badValueException with this message when the context value is a String that cannot be parsed as an integer. The getter first tries Numbers.parseInt and then a BigDecimal.intValueExact() (to accept trivial decimals like "12.00", mimicking Jackson); if both fail it gives up with this error. The key and the raw string value are reported.

Source

Thrown at processing/src/main/java/org/apache/druid/query/QueryContexts.java:378

  {
    if (value == null) {
      return null;
    } else if (value instanceof Number) {
      return ((Number) value).intValue();
    } else if (value instanceof String) {
      try {
        return Numbers.parseInt(value);
      }
      catch (NumberFormatException ignored) {

        // Attempt to handle trivial decimal values: 12.00, etc.
        // This mimics how Jackson will convert "12.00" to a Integer on request.
        try {
          return new BigDecimal((String) value).intValueExact();
        }
        catch (Exception nfe) {
          // That didn't work either. Give up.
          throw badValueException(key, "in integer format", value);
        }
      }
    }

    throw badTypeException(key, "an Integer", value);
  }

  /**
   * Get the value of a context value as an {@code int}. The value is expected
   * to be {@code null}, a string or a {@code Number} object.
   */
  public static int getAsInt(
      final String key,
      final Object value,
      final int defaultValue
  )
  {
    Integer val = getAsInt(key, value);

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Correct the context value to a plain integer string or JSON number: {"key": 100} or {"key": "100"}.
  2. If a fractional value is intended, round it at the client (Math.round) or use a float-typed context key instead.
  3. Strip units/separators before putting the value into the context.
  4. Catch the exception around getContextValue and fall back to the documented default.

Example fix

// before
{"timeout": "30s"}        // units not parsed -> IAE
// after
{"timeout": 30000}         // milliseconds as a number
// or
{"timeout": "30000"}
Defensive patterns

Strategy: validation

Validate before calling

Object v = context.get(key);
if (v instanceof String) {
  try { new java.math.BigDecimal((String) v).intValueExact(); }
  catch (Exception e) { throw new IllegalArgumentException("Context key '" + key + "' must be an integer, got: " + v); }
}

Type guard

boolean isParsableInt(Object v) {
  if (!(v instanceof String)) return v instanceof Number || v == null;
  try { new java.math.BigDecimal((String) v).intValueExact(); return true; } catch (Exception e) { return false; }
}

Try / catch

try {
  return query.getContextValue(key, defaultInt);
} catch (IllegalArgumentException e) {
  LOG.warn(e, "Non-integer value for context key [%s], using default", key);
  return defaultInt;
}

Prevention

When it happens

Trigger: Calling QueryContexts.getAsInt(key, value) (directly or via query.getContextValue(key, int default)) with a String value such as "12.5", "abc", "1e3", "" or a value with whitespace/units that is not exactly representable as an int.

Common situations: Users put human-formatted values like "100MB", "12.5", or "1,000" into numeric context keys (e.g. timeout, maxMergingPullThreads); locale-formatted numbers with thousands separators; fractional values supplied where the engine requires an integer.

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