{"record":{"id":"0b2af9a248ca0a7a","repo":"apache/shenyu","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":"error","filePath":"shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/shutdown/ShutdownHookManager.java","lineNumber":105,"sourceCode":"        list.sort((o1, o2) -> o2.priority - o1.priority);\n        List<Runnable> ordered = new ArrayList<>();\n        list.forEach(entry -> ordered.add(entry.hook));\n        return ordered;\n    }\n\n    /**\n     * Adds a shutdownHook with default priority zero, 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     */\n    public void addShutdownHook(final Runnable shutdownHook) {\n        if (Objects.isNull(shutdownHook)) {\n            throw new IllegalArgumentException(\"shutdownHook cannot be NULL\");\n        }\n        if (shutdownInProgress.get()) {\n            throw new IllegalStateException(\"Shutdown in progress, cannot add a shutdownHook\");\n        }\n        hooks.add(new HookEntry(shutdownHook, 0));\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    public void addShutdownHook(final Runnable shutdownHook, final int priority) {\n        if (Objects.isNull(shutdownHook)) {\n            throw new IllegalArgumentException(\"shutdownHook cannot be NULL\");\n        }\n        if (shutdownInProgress.get()) {\n            throw new IllegalStateException(\"Shutdown in progress, cannot add a shutdownHook\");","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/shutdown/ShutdownHookManager.java#L87-L123","documentation":"addShutdownHook also rejects registration once shutdown has begun: the manager flips an atomic `shutdownInProgress` flag when hooks start executing, and adding new hooks then is unsafe (they would never run or race the shutdown), so an IllegalStateException is thrown.","triggerScenarios":"Calling addShutdownHook after JVM shutdown started running hooks — e.g. an async task, Spring context close callback, or connection-close path that lazily registers a hook while the application is exiting.","commonSituations":"Late resource cleanup triggered by a shutdown of another component; tests shutting down one context while another lazily registers; retry logic that re-registers hooks during exit.","solutions":["Register shutdown hooks during normal startup, not from shutdown-triggered callbacks.","Check ShutdownHookManager.hasShutdownHookBeenRegistered()/isShutdownInProgress before registering and skip if already in progress.","Make the cleanup run inline instead of as a hook when called during shutdown."],"exampleFix":"// before\nmanager.addShutdownHook(client::close); // can run during shutdown\n// after\nif (!manager.isShutdownInProgress()) {\n    manager.addShutdownHook(client::close);\n} else {\n    client.close();\n}","handlingStrategy":"validation","validationCode":"if (manager.isShutdownInProgress()) {\n    // run inline instead of registering\n    hook.run();\n} else {\n    manager.addShutdownHook(hook);\n}","typeGuard":null,"tryCatchPattern":"try {\n    manager.addShutdownHook(hook);\n} catch (IllegalStateException e) {\n    LOGGER.warn(\"shutdown already started, running hook inline\");\n    hook.run();\n}","preventionTips":["Register hooks only during startup/bean initialization.","Do not register hooks from shutdown callbacks or other hooks.","Make cleanup logic callable both as a hook and inline."],"tags":["shutdown","illegal-state","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}