apache/iceberg · error · UnsupportedOperationException

NOOP timer has no duration

Error message

NOOP timer has no duration

What it means

The NOOP Timer discards all timing data, so it has no total duration to expose. totalDuration() throws UnsupportedOperationException to make accidental metric reads on the disabled timer fail fast instead of silently returning zero. Callers must use a real timer implementation to read durations.

Source

Thrown at api/src/main/java/org/apache/iceberg/metrics/Timer.java:145

    Timed NOOP = () -> {};
  }

  Timer NOOP =
      new Timer() {
        @Override
        public Timed start() {
          return Timed.NOOP;
        }

        @Override
        public long count() {
          throw new UnsupportedOperationException("NOOP timer has no count");
        }

        @Override
        public Duration totalDuration() {
          throw new UnsupportedOperationException("NOOP timer has no duration");
        }

        @Override
        public TimeUnit unit() {
          throw new UnsupportedOperationException("NOOP timer has no unit");
        }

        @Override
        public void record(long amount, TimeUnit unit) {}

        @Override
        public void time(Runnable runnable) {}

        @Override
        public <T> T timeCallable(Callable<T> callable) throws Exception {
          return callable.call();
        }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Instantiate a real timer (Timer.of / DefaultTimer) rather than Timer.NOOP wherever durations are read.
  2. Check for the NOOP instance before reading: skip or substitute Duration.ZERO when timer == Timer.NOOP.
  3. Wrap metric reads in try-catch for UnsupportedOperationException only if NOOP use is unavoidable in legacy paths.

Example fix

// before
Duration d = timer.totalDuration();
// after
Duration d = (timer == Timer.NOOP) ? Duration.ZERO : timer.totalDuration();
Defensive patterns

Strategy: type-guard

Validate before calling

boolean hasDuration = timer != Timer.NOOP;

Type guard

if (timer == Timer.NOOP) { return Duration.ZERO; } return timer.totalDuration();

Try / catch

try { return timer.totalDuration(); } catch (UnsupportedOperationException e) { return Duration.ZERO; }

Prevention

When it happens

Trigger: Calling Timer.NOOP.totalDuration(), or reading totalDuration() from a timer obtained through a metrics-disabled code path (Timer.Timed.NOOP / NOOP metrics context).

Common situations: Logging scan/commit timing summaries in code that runs with NOOP metrics enabled; tests asserting on durations without a real metrics implementation; dashboards or commit summary producers consuming Timer results unconditionally.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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