{"record":{"id":"fb7ad681ee5a1170","repo":"apache/shenyu","slug":"shutdown-in-progress-cannot-remove-a-shutdownhook","errorCode":null,"errorMessage":"Shutdown in progress, cannot remove a shutdownHook","messagePattern":"Shutdown in progress, cannot remove 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":135,"sourceCode":"     */\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\");\n        }\n        hooks.add(new HookEntry(shutdownHook, priority));\n    }\n\n    /**\n     * Removes a shutdownHook.\n     * @param shutdownHook shutdownHook to remove.\n     * @return TRUE if the shutdownHook was registered and removed,FALSE otherwise.\n     */\n    public boolean removeShutdownHook(final Runnable shutdownHook) {\n        if (shutdownInProgress.get()) {\n            throw new IllegalStateException(\"Shutdown in progress, cannot remove a shutdownHook\");\n        }\n        return hooks.remove(new HookEntry(shutdownHook, 0));\n    }\n\n    /**\n     * Indicates if a shutdownHook is registered or not.\n     *\n     * @param shutdownHook shutdownHook to check if registered.\n     * @return TRUE/FALSE depending if the shutdownHook is is registered.\n     */\n    public boolean hasShutdownHook(final Runnable shutdownHook) {\n        return hooks.contains(new HookEntry(shutdownHook, 0));\n    }\n\n    /**\n     * Indicates if shutdown is in progress or not.\n     *\n     * @return TRUE if the shutdown is in progress, otherwise FALSE.","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/shutdown/ShutdownHookManager.java#L117-L153","documentation":"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.","triggerScenarios":"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.","commonSituations":"Cancel-on-shutdown patterns where a component detaches its hook after it has already cleaned up; double-shutdown in tests (closing two contexts).","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."],"exampleFix":"// before\nmanager.removeShutdownHook(hook);\n// after\nif (!manager.isShutdownInProgress()) {\n    manager.removeShutdownHook(hook);\n}","handlingStrategy":"validation","validationCode":"if (!manager.isShutdownInProgress()) {\n    manager.removeShutdownHook(hook);\n}","typeGuard":null,"tryCatchPattern":"try {\n    manager.removeShutdownHook(hook);\n} catch (IllegalStateException e) {\n    // shutdown started; removal unnecessary, hook teardown is idempotent\n}","preventionTips":["Only remove hooks during normal runtime.","Make hook bodies idempotent so removal is optional.","Avoid cancel-on-shutdown coupling between components."],"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"}