{"record":{"id":"b5ee28859cf33a23","repo":"apache/hadoop","slug":"shutdown-in-progress-cannot-add-a-shutdownhook","errorCode":null,"errorMessage":"Shutdown in progress, cannot add a shutdownHook","messagePattern":"Shutdown in progress, cannot add a shutdownHook","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"warning","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/ShutdownHookManager.java","lineNumber":301,"sourceCode":"    return list;\n  }\n\n  /**\n   * Adds a shutdownHook with a priority, the higher the priority\n   * the earlier will run. ShutdownHooks with same priority run\n   * in a non-deterministic order.\n   *\n   * @param shutdownHook shutdownHook <code>Runnable</code>\n   * @param priority priority of the shutdownHook.\n   */\n  @InterfaceAudience.Public\n  @InterfaceStability.Stable\n  public void addShutdownHook(Runnable shutdownHook, int priority) {\n    if (shutdownHook == null) {\n      throw new IllegalArgumentException(\"shutdownHook cannot be NULL\");\n    }\n    if (shutdownInProgress.get()) {\n      throw new IllegalStateException(\"Shutdown in progress, cannot add a \" +\n          \"shutdownHook\");\n    }\n    hooks.add(new HookEntry(shutdownHook, priority));\n  }\n\n  /**\n   *\n   * Adds a shutdownHook with a priority and timeout the higher the priority\n   * the earlier will run. ShutdownHooks with same priority run\n   * in a non-deterministic order. The shutdown hook will be terminated if it\n   * has not been finished in the specified period of time.\n   *\n   * @param shutdownHook shutdownHook <code>Runnable</code>\n   * @param priority priority of the shutdownHook\n   * @param timeout timeout of the shutdownHook\n   * @param unit unit of the timeout <code>TimeUnit</code>\n   */\n  @InterfaceAudience.Public","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/ShutdownHookManager.java#L283-L319","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nShutdownHookManager.get().addShutdownHook(hook, SHUTDOWN_PRIORITY);\n\n// after\nif (!ShutdownHookManager.get().isShutdownInProgress()) {\n  ShutdownHookManager.get().addShutdownHook(hook, SHUTDOWN_PRIORITY);\n} else {\n  LOG.warn(\"Skipping shutdown hook registration; JVM shutdown in progress\");\n}","handlingStrategy":"try-catch","validationCode":"ShutdownHookManager mgr = ShutdownHookManager.get();\nif (!mgr.isShutdownInProgress()) {\n  mgr.addShutdownHook(hook, priority);\n}","typeGuard":null,"tryCatchPattern":"try {\n  ShutdownHookManager.get().addShutdownHook(hook, priority);\n} catch (IllegalStateException e) {\n  // JVM is shutting down: skip registration, optionally run hook inline if critical\n  LOG.debug(\"Skipped shutdown hook registration during JVM shutdown\", e);\n}","preventionTips":["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"],"tags":["hadoop","shutdown-hook","lifecycle","race-condition","illegalstate"],"backgroundTag":"illegal-state-during-shutdown","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}