apache/druid · error · IllegalArgumentException

precision [ ] must be in the range of [0,3]

Error message

precision [%d] must be in the range of [0,3]

What it means

The static HumanReadableBytes.format(long bytes, long precision, UnitSystem) validates that precision is between 0 and 3 inclusive and throws this IAE otherwise. Precision controls decimal places in the formatted string (pattern '%.<precision>f %s%s'). Any negative or >3 value is rejected before formatting.

Solutions

  1. Clamp precision to [0,3] before calling: Math.max(0, Math.min(3, p))
  2. Use precision 2 for the conventional '1.50 GB' style output
  3. If more decimals are needed, format manually with String.format outside this helper

Example fix

// before
HumanReadableBytes.format(1500, 4, UnitSystem.DECIMAL_BYTE); // IAE
// after
HumanReadableBytes.format(1500, 2, UnitSystem.DECIMAL_BYTE); // "1.50 KB"
Defensive patterns

Strategy: validation

Validate before calling

if (precision < 0 || precision > 3) {
  throw new IllegalArgumentException("precision must be in [0,3]: " + precision);
}

Type guard

int safePrecision = Math.max(0, Math.min(3, precision));

Try / catch

try {
  return HumanReadableBytes.format(bytes, precision, unitSystem);
} catch (IllegalArgumentException e) {
  return HumanReadableBytes.format(bytes, 2, unitSystem);
}

Prevention

When it happens

Trigger: Calling HumanReadableBytes.format(size, precision, unit) with precision < 0 or precision > 3, e.g. precision 4 for extra decimals or -1 intending 'auto'.

Common situations: Developers passing a computed or user-supplied decimal-places setting that was not clamped; assuming any non-negative precision is allowed; confusing this precision with significant digits.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/8748d906382cf3cd. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/java/util/common/HumanReadableBytes.java:250

    /**
     * simplified SI format without 'B' indicator
     * eg: K, M, G ...
     */
    DECIMAL
  }

  /**
   * Returns a human-readable string version of input value
   *
   * @param bytes      input value. Negative value is also allowed
   * @param precision  [0,3]
   * @param unitSystem which unit system is adopted to format the input value, see {@link UnitSystem}
   */
  public static String format(long bytes, long precision, UnitSystem unitSystem)
  {
    if (precision < 0 || precision > 3) {
      throw new IAE("precision [%d] must be in the range of [0,3]", precision);
    }

    String pattern = "%." + precision + "f %s%s";
    switch (unitSystem) {
      case BINARY_BYTE:
        return BinaryFormatter.format(bytes, pattern, "B");
      case DECIMAL_BYTE:
        return DecimalFormatter.format(bytes, pattern, "B");
      case DECIMAL:
        return DecimalFormatter.format(bytes, pattern, "").trim();
      default:
        throw new IAE("Unkonwn unit system[%s]", unitSystem);
    }
  }

  static class BinaryFormatter
  {
    private static final String[] UNITS = {"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"};

View on GitHub (pinned to 9b90983fd2)