apache/beam · error · UnsupportedOperationException

Timer not supported. Use histogram instead.

Error message

Timer not supported. Use histogram instead.

What it means

AdaptableCollector explicitly rejects timers: getTimer always throws UnsupportedOperationException. The adapter layer maps counters and histograms onto Beam accumulators but has no timer equivalent, so users are directed to histograms.

Solutions

  1. Use getHistogram(name) instead and record elapsed milliseconds
  2. Remove timer metrics from the user function
  3. Accumulate timing values in your own state and report them outside the collector

Example fix

// before
collector.getTimer("myTimer").update(elapsed);
// after
collector.getHistogram("myDurationMs").update(elapsed);
Defensive patterns

Strategy: validation

Validate before calling

// never call getTimer on AdaptableCollector; use histogram for durations
// long ms = ...; collector.getHistogram("durationMs").update(ms);

Type guard

null

Try / catch

try { collector.getTimer("t"); } catch (UnsupportedOperationException e) { /* use getHistogram instead */ }

Prevention

When it happens

Trigger: Calling collector.getTimer(name) from inside a Euphoria user function (map/flatmap/reduce) running through the Beam translation with an AdaptableCollector.

Common situations: Porting Flink/Spark Euphoria code that used timers to Beam; measuring operation durations in user DoFns.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/01343b0fc7185a62. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/euphoria/src/main/java/org/apache/beam/sdk/extensions/euphoria/core/translate/collector/AdaptableCollector.java:88

  @Override
  public Context asContext() {
    return this;
  }

  @Override
  public Counter getCounter(String name) {
    return accumulators.getCounter(requireNonNull(operatorName, UNSUPPORTED), name);
  }

  @Override
  public Histogram getHistogram(String name) {
    return accumulators.getHistogram(requireNonNull(operatorName, UNSUPPORTED), name);
  }

  @Override
  public Timer getTimer(String name) {
    throw new UnsupportedOperationException("Timer not supported. Use histogram instead.");
  }

  public void setProcessContext(DoFn<InputT, OutputT>.ProcessContext context) {
    this.context = requireNonNull(context);
  }
}

View on GitHub (pinned to 12126d8942)