apache/druid · error · BadQueryContextException

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

Error message

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

What it means

QueryContexts.getAsFloat(key, value) throws badValueException with this message when the context value is a String that Float.parseFloat cannot parse. Unlike the int/long getters there is no BigDecimal fallback: any non-float string (including "1,5", "12.5f", "", or values with units) is rejected. The error names the key and the offending string.

Source

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

    return val == null ? defaultValue : val;
  }

  /**
   * Get the value of a context value as an {@code Float}. The value is expected
   * to be {@code null}, a string or a {@code Number} object.
   */
  public static Float getAsFloat(final String key, final Object value)
  {
    if (value == null) {
      return null;
    } else if (value instanceof Number) {
      return ((Number) value).floatValue();
    } else if (value instanceof String) {
      try {
        return Float.parseFloat((String) value);
      }
      catch (NumberFormatException ignored) {
        throw badValueException(key, "in float format", value);
      }
    }
    throw badTypeException(key, "a Float", value);
  }

  public static float getAsFloat(
      final String key,
      final Object value,
      final float defaultValue
  )
  {
    Float val = getAsFloat(key, value);
    return val == null ? defaultValue : val;
  }

  public static HumanReadableBytes getAsHumanReadableBytes(
      final String key,
      final Object value,

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Send the value as a JSON number or a canonical float string: {"key": 0.75} or "0.75".
  2. Use '.' as the decimal separator and strip '%' and other decorations at the client.
  3. If an integer is what the engine actually needs, use an integer-typed context key instead.
  4. Catch the exception around getContextValue and fall back to the default.

Example fix

// before
{"partitioningThreshold": "50%"}  // -> IAE
// after
{"partitioningThreshold": 0.5}
Defensive patterns

Strategy: validation

Validate before calling

Object v = context.get(key);
if (v instanceof String) {
  try { Float.parseFloat((String) v); }
  catch (NumberFormatException e) { throw new IllegalArgumentException("Context key '" + key + "' must be a float, got: " + v); }
}

Type guard

boolean isParsableFloat(Object v) {
  if (!(v instanceof String)) return v instanceof Number || v == null;
  try { Float.parseFloat((String) v); return true; } catch (NumberFormatException e) { return false; }
}

Try / catch

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

Prevention

When it happens

Trigger: Calling QueryContexts.getAsFloat(key, value) or query.getContextValue(key, float default) with a String context value such as "abc", "12.5%", "1,5", or an empty string where a float is required.

Common situations: Percentage or ratio parameters supplied with a '%' sign or comma decimal separator; locale-formatted decimals; fractional thresholds written with units ("0.5x").

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