apache/druid · error · IllegalArgumentException
Unkonwn unit system[ ]
Error message
Unkonwn unit system[%s]
What it means
HumanReadableBytes.format switches over the provided UnitSystem enum; the default branch throws this (typo 'Unkonwn') if the unit system is not one of BINARY_BYTE, DECIMAL_BYTE, DECIMAL. Since UnitSystem is an enum, reaching default is nearly impossible in normal Java but can occur with foreign enum constants in switching/reflection-based scenarios or when the enum gains new constants in one version while this method's switch lags.
Solutions
- Pass only HumanReadableBytes.UnitSystem.BINARY_BYTE, DECIMAL_BYTE, or DECIMAL
- Null-check the UnitSystem argument before calling format
- After upgrading Druid, recompile so enum switches are exhaustive against the new version
Example fix
// before HumanReadableBytes.format(1024, 2, null); // IAE/NPE at default // after HumanReadableBytes.format(1024, 2, UnitSystem.BINARY_BYTE);
Defensive patterns
Strategy: type-guard
Validate before calling
if (unitSystem == null) {
throw new IllegalArgumentException("unitSystem must not be null");
} Type guard
if (unitSystem == HumanReadableBytes.UnitSystem.BINARY_BYTE
|| unitSystem == HumanReadableBytes.UnitSystem.DECIMAL_BYTE
|| unitSystem == HumanReadableBytes.UnitSystem.DECIMAL) {
// safe to format
} Try / catch
try {
return HumanReadableBytes.format(bytes, precision, unitSystem);
} catch (IllegalArgumentException e) {
return HumanReadableBytes.format(bytes, precision, HumanReadableBytes.UnitSystem.DECIMAL_BYTE);
} Prevention
- Only pass the three declared UnitSystem constants
- Null-check enum parameters coming from deserialization or maps
- Recompile after Druid upgrades that touch the UnitSystem enum
When it happens
Trigger: Passing null as the UnitSystem (switch on null throws NPE, but older/greedy dispatch paths can hit default), or a custom/newly added UnitSystem constant not covered by the switch after a library upgrade.
Common situations: Reflective or serialized enum values from another Druid version; code written against a fork of the enum; dynamic dispatch frameworks mapping integers to enum constants.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- precision [ ] must be in the range of [0,3]
- Ambiguous directions
- defensive
- Expected key [ ] to be referring to one of the values [ ]…
- Invalid druid.storage.transfer.asyncHttpClientType
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/ebb904bbae6e3446.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/java/util/common/HumanReadableBytes.java:262
* @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"};
static String format(long bytes, String pattern, String suffix)
{
if (bytes > -1024 && bytes < 1024) {
return bytes + " " + suffix;
}
if (bytes == Long.MIN_VALUE) {
/**
* special path for Long.MIN_VALUE
*
* Long.MIN_VALUE = 2^63 = (2^60=1EiB) * 2^3View on GitHub (pinned to 9b90983fd2)