apache/shenyu · error · IllegalStateException
Timer already shutdown
Error message
Timer already shutdown
What it means
HierarchicalWheelTimer.start() throws IllegalStateException when the timer's single-thread task executor has already been shut down. The timer lazily starts its worker thread on first task add; once stop() has been called the executor is terminated and no further scheduling is permitted. This guards against silently accepting tasks into a dead timer.
Solutions
- Do not reuse the timer after shutdown; create a new HierarchicalWheelTimer instance for post-shutdown scheduling.
- Check timer state before adding tasks (expose or track an 'isShutdown' flag) and skip/re-route tasks.
- Fix lifecycle ordering: stop the timer only after all producers that schedule tasks have been stopped.
- If the shutdown was unintentional, audit shutdown-hook / @PreDestroy code paths that call the timer's stop method.
Example fix
// before
timer.stop();
timer.add(task); // IllegalStateException: Timer already shutdown
// after
if (!timer.isShutdown()) {
timer.add(task);
} else {
timer = new HierarchicalWheelTimer(...);
timer.add(task);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (timer.isShutdown()) { /* skip or recreate timer */ } Type guard
boolean usable = timer != null && !timer.isShutdown();
Try / catch
try { timer.add(task); } catch (IllegalStateException e) { LOG.warn("timer stopped, dropping task", e); } Prevention
- Track timer lifecycle centrally; no scheduling after stop()
- Recreate the timer instead of reusing a shut-down instance
- Order shutdown hooks: producers stop before timer stop
- Add integration tests for shutdown-during-traffic scenarios
When it happens
Trigger: Calling add(...) (or another method that invokes start()) on a HierarchicalWheelTimer after its shutdown/stop method has been executed.
Common situations: Application shutdown hooks stopping the timer while in-flight requests still try to schedule delayed tasks; plugin code caching a timer reference after the gateway context was reloaded; accidentally calling stop() then reusing the singleton timer instead of creating a new one.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Shutdown in progress, cannot add a shutdownHook
- Shutdown in progress, cannot remove a shutdownHook
- Executor is shutdown!
- shutdownHook cannot be NULL
- no more memory can be used !
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/eddef58c9a5d5553.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-common/src/main/java/org/apache/shenyu/common/timer/HierarchicalWheelTimer.java:139
writeLock.lock();
try {
if (taskExecutor.isShutdown()) {
return;
}
while (Objects.nonNull(bucket)) {
timingWheel.advanceClock(bucket.getExpiration());
bucket.flush(this::addTimerTaskEntry);
bucket = delayQueue.poll();
}
} finally {
writeLock.unlock();
}
}
}
private void start() {
if (taskExecutor.isShutdown()) {
throw new IllegalStateException("Timer already shutdown");
}
int state = WORKER_STATE_UPDATER.get(this);
if (state == 0) {
if (WORKER_STATE_UPDATER.compareAndSet(this, 0, 1)) {
workerThread.start();
}
}
}
@Override
public int size() {
return taskCounter.get();
}
@Override
public void shutdown() {
writeLock.lock();
try {View on GitHub (pinned to 567142e072)