apache/hadoop · warning · IllegalStateException
Shutdown in progress, cannot add a shutdownHook
Error message
Shutdown in progress, cannot add a shutdownHook
What it means
ShutdownHookManager.addShutdownHook throws IllegalStateException once the JVM shutdown sequence has started (the manager's own hook is draining its prioritized queue). Registering new hooks mid-shutdown is unsafe, so it is refused. This is a lifecycle race: initialization code losing to JVM termination.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/ShutdownHookManager.java:301
return list;
}
/**
* Adds a shutdownHook with a priority, the higher the priority
* the earlier will run. ShutdownHooks with same priority run
* in a non-deterministic order.
*
* @param shutdownHook shutdownHook <code>Runnable</code>
* @param priority priority of the shutdownHook.
*/
@InterfaceAudience.Public
@InterfaceStability.Stable
public void addShutdownHook(Runnable shutdownHook, int priority) {
if (shutdownHook == null) {
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));
}
/**
*
* Adds a shutdownHook with a priority and timeout the higher the priority
* the earlier will run. ShutdownHooks with same priority run
* in a non-deterministic order. The shutdown hook will be terminated if it
* has not been finished in the specified period of time.
*
* @param shutdownHook shutdownHook <code>Runnable</code>
* @param priority priority of the shutdownHook
* @param timeout timeout of the shutdownHook
* @param unit unit of the timeout <code>TimeUnit</code>
*/
@InterfaceAudience.PublicView on GitHub (pinned to 2add963021)
Solutions
- Guard registration: if (!ShutdownHookManager.get().isShutdownInProgress()) { manager.addShutdownHook(hook, prio); }
- Make startup lifecycle-aware: do not begin component initialization after stop() was requested (check your own stopping flag)
- Catch IllegalStateException around the registration call in code that can race shutdown and treat it as benign
- Shut down background initializer threads before System.exit so they cannot register during exit
Example fix
// before
ShutdownHookManager.get().addShutdownHook(hook, SHUTDOWN_PRIORITY);
// after
if (!ShutdownHookManager.get().isShutdownInProgress()) {
ShutdownHookManager.get().addShutdownHook(hook, SHUTDOWN_PRIORITY);
} else {
LOG.warn("Skipping shutdown hook registration; JVM shutdown in progress");
} Defensive patterns
Strategy: try-catch
Validate before calling
ShutdownHookManager mgr = ShutdownHookManager.get();
if (!mgr.isShutdownInProgress()) {
mgr.addShutdownHook(hook, priority);
} Try / catch
try {
ShutdownHookManager.get().addShutdownHook(hook, priority);
} catch (IllegalStateException e) {
// JVM is shutting down: skip registration, optionally run hook inline if critical
LOG.debug("Skipped shutdown hook registration during JVM shutdown", e);
} Prevention
- Check isShutdownInProgress() (and your own stopping flag) before registering hooks from background threads
- Register hooks eagerly at startup instead of lazily to shrink the race window
- Stop initializer threads before System.exit so they cannot register during shutdown
- Treat registration IllegalStateException during shutdown as benign — log at debug, not error
When it happens
Trigger: A lazily started service, daemon thread, or @PostConstruct registering a hook while ShutdownHookManager.get().isShutdownInProgress() is true — e.g. Ctrl+C/SIGTERM arrives while background components are still wiring up; second phase of a rolling restart beginning during shutdown.
Common situations: Servlet container hot-redeploys starting new contexts as the old JVM exits; test JVMs that finish while async threads initialize clients; applications spawned by supervisors (YARN NodeManager, systemd) receiving SIGTERM during startup.
Related errors
- Shutdown in progress, cannot remove a shutdownHook
- shutdownHook cannot be NULL
- AsyncDataService is already shutdown
- key + ": Stream is closed!"
- Stream closed
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/b5ee28859cf33a23.
Report an issue: GitHub.