apache/iceberg · error · IllegalArgumentException

Unsupported counter

Error message

Unsupported counter: '%s'

What it means

HadoopMetricsContext.counter(String, Class) only supports WRITE_BYTES and WRITE_OPERATIONS counters and type-checks each (WRITE_OPERATIONS requires Integer). Any other Counter.Name, or a wrong type parameter, throws IllegalArgumentException.

Solutions

  1. Only request WRITE_BYTES or WRITE_OPERATIONS from HadoopMetricsContext
  2. Use Integer.class as the type for WRITE_OPERATIONS
  3. Route other counter names to the appropriate MetricsContext implementation

Example fix

// before
Counter<Long> c = metrics.counter(Counter.Name.WRITE_OPERATIONS, Long.class); // throws
// after
Counter<Integer> c = metrics.counter(Counter.Name.WRITE_OPERATIONS, Integer.class);
Defensive patterns

Strategy: validation

Validate before calling

Set<Counter.Name> SUPPORTED = Set.of(Counter.Name.WRITE_BYTES, Counter.Name.WRITE_OPERATIONS);
if (!SUPPORTED.contains(name)) {
  throw new IllegalArgumentException("HadoopMetricsContext only supports WRITE_BYTES/WRITE_OPERATIONS");
}
if (name == Counter.Name.WRITE_OPERATIONS && type != Integer.class) {
  throw new IllegalArgumentException("WRITE_OPERATIONS requires Integer.class");
}

Try / catch

try { return ctx.counter(name, type); }
catch (IllegalArgumentException e) { LOG.warn("Counter {} unsupported by Hadoop context", name); return Counter.noop(); }

Prevention

When it happens

Trigger: Calling counter(name, type) with a counter name other than WRITE_BYTES/WRITE_OPERATIONS, or WRITE_OPERATIONS with a type other than Integer.class (e.g. Long.class).

Common situations: Custom metrics integrations requesting a counter name defined elsewhere (e.g. from another metrics context); refactors that widened Integer to Long; passing generic Counter.Name constants not present in this Hadoop context.

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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/hadoop/HadoopMetricsContext.java:85

  @SuppressWarnings("unchecked")
  public <T extends Number> Counter<T> counter(String name, Class<T> type, Unit unit) {
    switch (name) {
      case READ_BYTES:
        ValidationException.check(type == Long.class, "'%s' requires Long type", READ_BYTES);
        return (Counter<T>) longCounter(statistics()::incrementBytesRead);
      case READ_OPERATIONS:
        ValidationException.check(
            type == Integer.class, "'%s' requires Integer type", READ_OPERATIONS);
        return (Counter<T>) integerCounter(statistics()::incrementReadOps);
      case WRITE_BYTES:
        ValidationException.check(type == Long.class, "'%s' requires Long type", WRITE_BYTES);
        return (Counter<T>) longCounter(statistics()::incrementBytesWritten);
      case WRITE_OPERATIONS:
        ValidationException.check(
            type == Integer.class, "'%s' requires Integer type", WRITE_OPERATIONS);
        return (Counter<T>) integerCounter(statistics()::incrementWriteOps);
      default:
        throw new IllegalArgumentException(String.format("Unsupported counter: '%s'", name));
    }
  }

  private Counter<Long> longCounter(Consumer<Long> consumer) {
    return new Counter<Long>() {
      @Override
      public void increment() {
        increment(1L);
      }

      @Override
      public void increment(Long amount) {
        consumer.accept(amount);
      }
    };
  }

  private Counter<Integer> integerCounter(Consumer<Integer> consumer) {

View on GitHub (pinned to 86d9c8fc54)