apache/iceberg · error · IllegalArgumentException

Invalid unit: %s

Error message

Invalid unit: %s

What it means

MetricsContext.Unit.fromDisplayName converts a user-facing unit string to the Unit enum, uppercasing it first; null throws 'Invalid unit: null' and any string that is not a valid Unit name (bytes, bytes_i32, bytes_i64, count, none, timestamps, time) throws 'Invalid unit: <value>'. It preserves the cause from Unit.valueOf.

Source

Thrown at api/src/main/java/org/apache/iceberg/metrics/MetricsContext.java:53

    BYTES("bytes"),
    COUNT("count");

    private final String displayName;

    Unit(String displayName) {
      this.displayName = displayName;
    }

    public String displayName() {
      return displayName;
    }

    public static Unit fromDisplayName(String displayName) {
      Preconditions.checkArgument(null != displayName, "Invalid unit: null");
      try {
        return Unit.valueOf(displayName.toUpperCase(Locale.ROOT));
      } catch (IllegalArgumentException e) {
        throw new IllegalArgumentException(String.format("Invalid unit: %s", displayName), e);
      }
    }
  }

  default void initialize(Map<String, String> properties) {}

  /**
   * @deprecated will be removed in 2.0.0, use {@link org.apache.iceberg.metrics.Counter} instead.
   */
  @Deprecated
  interface Counter<T extends Number> {
    /** Increment the counter by a single whole number value (i.e. 1). */
    void increment();

    /**
     * Increment the counter by the provided amount.
     *
     * @param amount to be incremented

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use one of the exact Unit enum names (case-insensitive): bytes, bytes_i32, bytes_i64, count, none, timestamps, time
  2. Check the property value for typos or whitespace before calling fromDisplayName
  3. Guard against null/empty input before conversion
  4. Catch IllegalArgumentException and fall back to a default Unit

Example fix

// before
Unit u = Unit.fromDisplayName(props.get("unit"));
// after
String raw = props.get("unit");
Unit u = (raw != null && !raw.isEmpty())
    ? Unit.fromDisplayName(raw)
    : Unit.COUNT;
Defensive patterns

Strategy: validation

Validate before calling

if (displayName == null || displayName.isEmpty()) { default; }

Try / catch

try { Unit.fromDisplayName(s); } catch (IllegalArgumentException e) { use default; }

Prevention

When it happens

Trigger: Parsing a metrics unit from a table/user property (e.g. 'counter-unit') that is misspelled, empty-but-non-null, or in a different language/lowercase abbreviation like 'b' or 'counts'.

Common situations: Config mistakes in properties files (e.g. 'bytese', 'Counts'); users passing human-friendly units like 'bytes' vs enum names like 'BYTES' — note fromDisplayName uppercases, so only exact enum names case-insensitively work; locale issues.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/ee208a6d454e70fc. Report an issue: GitHub.