apache/shenyu · error · IllegalStateException
Shutdown in progress, cannot remove a shutdownHook
Error message
Shutdown in progress, cannot remove a shutdownHook
What it means
removeShutdownHook unregisters a previously added hook. Once shutdown has started, mutation of the hook list is forbidden (hooks are being executed in priority order), so any removal attempt throws IllegalStateException regardless of whether the hook was registered.
Solutions
- Remove hooks during normal application lifetime only; accept that during shutdown removal is a no-op and wrap the call in a state check.
- Check isShutdownInProgress() before removing and skip silently.
- Redesign so hook execution itself is idempotent, making removal unnecessary.
Example fix
// before
manager.removeShutdownHook(hook);
// after
if (!manager.isShutdownInProgress()) {
manager.removeShutdownHook(hook);
} Defensive patterns
Strategy: validation
Validate before calling
if (!manager.isShutdownInProgress()) {
manager.removeShutdownHook(hook);
} Try / catch
try {
manager.removeShutdownHook(hook);
} catch (IllegalStateException e) {
// shutdown started; removal unnecessary, hook teardown is idempotent
} Prevention
- Only remove hooks during normal runtime.
- Make hook bodies idempotent so removal is optional.
- Avoid cancel-on-shutdown coupling between components.
When it happens
Trigger: Calling removeShutdownHook during JVM shutdown — e.g. a Spring destroy callback or a hook that tries to cancel peer hooks while the manager is executing them.
Common situations: Cancel-on-shutdown patterns where a component detaches its hook after it has already cleaned up; double-shutdown in tests (closing two contexts).
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
- shutdownHook cannot be NULL
- Executor is shutdown!
- Timer already shutdown
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/fb7ad681ee5a1170.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/shutdown/ShutdownHookManager.java:135
*/
public void addShutdownHook(final Runnable shutdownHook, final int priority) {
if (Objects.isNull(shutdownHook)) {
throw new IllegalArgumentException("shutdownHook cannot be NULL");
}
if (shutdownInProgress.get()) {
throw new IllegalStateException("Shutdown in progress, cannot add a shutdownHook");
}
hooks.add(new HookEntry(shutdownHook, priority));
}
/**
* Removes a shutdownHook.
* @param shutdownHook shutdownHook to remove.
* @return TRUE if the shutdownHook was registered and removed,FALSE otherwise.
*/
public boolean removeShutdownHook(final Runnable shutdownHook) {
if (shutdownInProgress.get()) {
throw new IllegalStateException("Shutdown in progress, cannot remove a shutdownHook");
}
return hooks.remove(new HookEntry(shutdownHook, 0));
}
/**
* Indicates if a shutdownHook is registered or not.
*
* @param shutdownHook shutdownHook to check if registered.
* @return TRUE/FALSE depending if the shutdownHook is is registered.
*/
public boolean hasShutdownHook(final Runnable shutdownHook) {
return hooks.contains(new HookEntry(shutdownHook, 0));
}
/**
* Indicates if shutdown is in progress or not.
*
* @return TRUE if the shutdown is in progress, otherwise FALSE.View on GitHub (pinned to 567142e072)