apache/beam · error · IllegalArgumentException
Cannot output timer with output timestamp
Error message
Cannot output timer with output timestamp %s. Output timestamps must be no earlier than the timestamp of the current input (%s) minus the allowed skew (%s) and no later than %s. See the DoFn#getAllowedTimestampSkew() Javadoc for details on changing the allowed skew.
What it means
Thrown when a DoFn sets a timer with an output timestamp that falls outside the permitted window: it must not be earlier than the current input (or timer hold) timestamp minus the DoFn's allowed timestamp skew, and not later than BoundedWindow.TIMESTAMP_MAX_VALUE. This enforces the DoFn#getAllowedTimestampSkew contract in the Fn API harness.
Solutions
- Return a larger value from DoFn#getAllowedTimestampSkew() (e.g. Duration.standardHours(1)) so the lower bound covers your timer timestamps.
- Clamp the timer's output timestamp to be >= input timestamp minus allowed skew before setting it.
- Ensure the timer timestamp is not after BoundedWindow.TIMESTAMP_MAX_VALUE; clamp to that constant if needed.
- Verify arithmetic on Instant timestamps (minus/add) isn't overflowing; the harness clamps overflow but the resulting comparison can still fail.
Example fix
// before
@GetAllowedTimestampSkew
public Duration getAllowedTimestampSkew() { return Duration.ZERO; }
timer.offset(Duration.standardMinutes(-30));
// after
@GetAllowedTimestampSkew
public Duration getAllowedTimestampSkew() { return Duration.standardHours(1); } Defensive patterns
Strategy: validation
Validate before calling
Duration skew = doFn.getAllowedTimestampSkew();
Instant lower = inputTs.minus(skew);
if (timerTs.isBefore(lower) || timerTs.isAfter(BoundedWindow.TIMESTAMP_MAX_VALUE)) {
timerTs = max(timerTs, lower); // clamp before setting
} Try / catch
try {
timer.offset(d);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("Timer timestamp outside allowed skew; increase @GetAllowedTimestampSkew", e);
} Prevention
- Declare @GetAllowedTimestampSkew large enough for all backward timer timestamps
- Clamp timer timestamps against input timestamp minus skew
- Avoid Instant arithmetic that can overflow near TIMESTAMP_MIN/MAX
When it happens
Trigger: Calling Timer.set(...)/offset/onTimer callbacks where the computed output timestamp is before inputTimestamp.minus(allowedTimestampSkew) or after TIMESTAMP_MAX_VALUE, inside a timer-aware DoFn executed by FnApiDoFnRunner.
Common situations: Setting a timer with a timestamp far in the past relative to the element's timestamp; using Instant.minus() that under/overflows; overriding getAllowedTimestampSkew with a small value while emitting early timestamps; windowing edge cases near the timestamp min/max bounds.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Cannot output with timestamp
- BigQuery data contained value
- Converting BigQuery type to Beam type is unsupported
- Duplicate timer family ID
- ProcessElement doesn't use a TimerProvider, but Timer field…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/9722018504a12e60.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/harness/src/main/java/org/apache/beam/fn/harness/FnApiDoFnRunner.java:1450
return target;
}
private Timer<K> getClearedTimer() {
return Timer.cleared(userKey, dynamicTimerTag, Collections.singletonList(boundedWindow));
}
@SuppressWarnings("deprecation") // Allowed Skew is deprecated for users, but must be respected
private Timer<K> getTimerForTime(Instant scheduledTime) {
if (outputTimestamp != null) {
Instant lowerBound;
try {
lowerBound = elementTimestampOrTimerHoldTimestamp.minus(doFn.getAllowedTimestampSkew());
} catch (ArithmeticException e) {
lowerBound = BoundedWindow.TIMESTAMP_MIN_VALUE;
}
if (outputTimestamp.isBefore(lowerBound)
|| outputTimestamp.isAfter(BoundedWindow.TIMESTAMP_MAX_VALUE)) {
throw new IllegalArgumentException(
String.format(
"Cannot output timer with output timestamp %s. Output timestamps must be no "
+ "earlier than the timestamp of the current input (%s) minus the allowed skew "
+ "(%s) and no later than %s. See the DoFn#getAllowedTimestampSkew() Javadoc for "
+ "details on changing the allowed skew.",
outputTimestamp,
elementTimestampOrTimerHoldTimestamp,
doFn.getAllowedTimestampSkew().getMillis() >= Integer.MAX_VALUE
? doFn.getAllowedTimestampSkew()
: PeriodFormat.getDefault().print(doFn.getAllowedTimestampSkew().toPeriod()),
BoundedWindow.TIMESTAMP_MAX_VALUE));
}
}
// Output timestamp is set to the delivery time if not initialized by an user.
if (!noOutputTimestamp
&& outputTimestamp == null
&& TimeDomain.EVENT_TIME.equals(timeDomain)) {View on GitHub (pinned to 12126d8942)