apache/iceberg · error · IllegalArgumentException

Counter for type %s is not supported

Error message

Counter for type %s is not supported

What it means

This is the logging/no-op MetricsContext inside MetricsContext: counter(name, type) returns DefaultCounter.NOOP for Integer and Long, but any other Number type throws IllegalArgumentException('Counter for type %s is not supported'). Even in a no-op context the counter type must still be Integer or Long.

Source

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

      @Override
      public Timer timer(String name, TimeUnit unit) {
        return Timer.NOOP;
      }

      @Override
      @SuppressWarnings("unchecked")
      public <T extends Number> Counter<T> counter(String name, Class<T> type, Unit unit) {
        if (Integer.class.equals(type)) {
          return (Counter<T>)
              ((DefaultCounter) org.apache.iceberg.metrics.DefaultCounter.NOOP).asIntCounter();
        }

        if (Long.class.equals(type)) {
          return (Counter<T>)
              ((DefaultCounter) org.apache.iceberg.metrics.DefaultCounter.NOOP).asLongCounter();
        }

        throw new IllegalArgumentException(
            String.format("Counter for type %s is not supported", type.getName()));
      }

      @Override
      public org.apache.iceberg.metrics.Counter counter(String name, Unit unit) {
        return org.apache.iceberg.metrics.DefaultCounter.NOOP;
      }
    };
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use Integer.class or Long.class as the counter type
  2. Use DefaultMetricsContext if you need real values or other types via different mechanisms
  3. Catch IllegalArgumentException and skip the metric for unsupported types

Example fix

// before
Counter<Double> c = noopCtx.counter("x", Double.class, Unit.COUNT); // throws
// after
Counter<Long> c = noopCtx.counter("x", Long.class, Unit.COUNT); // NOOP counter
Defensive patterns

Strategy: validation

Validate before calling

if (type != Integer.class && type != Long.class) type = Long.class;

Type guard

boolean ok(Class<?> t) { return t == Integer.class || t == Long.class; }

Try / catch

try { noopCtx.counter(...) } catch (IllegalArgumentException e) { use Long.class }

Prevention

When it happens

Trigger: Calling counter(name, Double.class, unit) (or any non-int/long type) on the no-op/logging context returned by MetricsContext.unsupportedCounter-style defaults.

Common situations: Assuming the no-op context accepts any metric type since it discards data anyway; refactoring counter types to Double without checking the context.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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