google/guava · error · UnsupportedOperationException
scheduleAtFixedRate is not supported.
Error message
scheduleAtFixedRate is not supported.
What it means
SameThreadScheduledExecutorService is a deliberately minimal synchronous test double that runs submitted tasks on the caller thread. It implements one-shot scheduling but intentionally does not support periodic scheduling; scheduleAtFixedRate throws UnsupportedOperationException by design.
Source
Thrown at android/guava-testlib/src/com/google/common/util/concurrent/testing/SameThreadScheduledExecutorService.java:180
}
@Override
public long getDelay(TimeUnit unit) {
Preconditions.checkNotNull(unit, "unit must not be null!");
return 0;
}
@Override
public int compareTo(Delayed other) {
Preconditions.checkNotNull(other, "other must not be null!");
return 0;
}
}
@Override
public ListenableScheduledFuture<?> scheduleAtFixedRate(
Runnable command, long initialDelay, long period, TimeUnit unit) {
throw new UnsupportedOperationException("scheduleAtFixedRate is not supported.");
}
@Override
public ListenableScheduledFuture<?> scheduleWithFixedDelay(
Runnable command, long initialDelay, long delay, TimeUnit unit) {
throw new UnsupportedOperationException("scheduleWithFixedDelay is not supported.");
}
}
View on GitHub (pinned to 94f39958ba)
Solutions
- Switch the test to a real ScheduledThreadPoolExecutor (or a more complete fake) for code paths that use scheduleAtFixedRate.
- Refactor the code under test to depend on an abstraction (e.g. a Scheduler interface) so periodic scheduling can be stubbed without going through this executor.
- Split the test so the periodic-scheduling path is exercised against a real executor while only the synchronous parts use this fake.
- Avoid scheduling at a fixed rate; use repeated one-shot schedule(...) calls the fake does support.
Example fix
// before SameThreadScheduledExecutorService ex = new SameThreadScheduledExecutorService(); ex.scheduleAtFixedRate(task, 0, 1, SECONDS); // UnsupportedOperationException // after ScheduledExecutorService ex = Executors.newScheduledThreadPool(1); ex.scheduleAtFixedRate(task, 0, 1, SECONDS);
Defensive patterns
Strategy: validation
Validate before calling
// Only inject the fake when the code path does not use fixed-rate scheduling.
boolean usesFixedRate = schedulingType == SchedulingType.AT_FIXED_RATE;
ScheduledExecutorService ex = usesFixedRate
? Executors.newScheduledThreadPool(1)
: new SameThreadScheduledExecutorService(); Type guard
// Detect capability before calling, since the fake lacks it.
boolean supportsFixedRate(ScheduledExecutorService ex) {
return !(ex instanceof SameThreadScheduledExecutorService);
} Try / catch
// UnsupportedOperationException is a programmer error in test setup; do not // catch and continue. Switch executors instead.
Prevention
- Do not inject SameThreadScheduledExecutorService into code that calls scheduleAtFixedRate.
- Use a real ScheduledThreadPoolExecutor for periodic-scheduling paths.
- Abstract scheduling behind an interface so tests can stub it directly.
- Map out which ScheduledExecutorService operations the fake supports before wiring it.
When it happens
Trigger: Code under test calls executor.scheduleAtFixedRate(command, initialDelay, period, unit) on an instance of SameThreadScheduledExecutorService provided by a test.
Common situations: Injecting this fake executor into code that performs periodic scheduling (polling, retries, cleanup loops); migrating tests from a real ScheduledExecutorService without realizing the fake omits fixed-rate scheduling.
Related errors
- scheduleWithFixedDelay is not supported.
- Unexpected interrupt while waiting for future
- Unexpected interrupt while waiting for latch
- %s returns null and cannot be used to test instance methods.
- at index %s
AI-assisted analysis of google/guava@94f39958ba (2026-08-13).
Data as JSON: /api/errors/35fcef64dd17e215.
Report an issue: GitHub.