{"record":{"id":"e8e8836651a48bff","repo":"apache/shenyu","slug":"shutdownhook-cannot-be-null","errorCode":null,"errorMessage":"shutdownHook cannot be NULL","messagePattern":"shutdownHook cannot be NULL","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/shutdown/ShutdownHookManager.java","lineNumber":102,"sourceCode":"        synchronized (MGR.hooks) {\n            list = new ArrayList<>(MGR.hooks);\n        }\n        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\");","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/shutdown/ShutdownHookManager.java#L84-L120","documentation":"ShutdownHookManager.addShutdownHook registers a Runnable to run at JVM/client shutdown. It validates arguments first: a null hook is rejected with IllegalArgumentException because HookEntry wrapping and later execution assume a non-null Runnable.","triggerScenarios":"Calling ShutdownHookManager.getInstance().addShutdownHook(null), typically when a hook variable comes from an unset config/optional bean or a failed initialization returns null.","commonSituations":"Conditional resource cleanup code where the resource was never created (so the Runnable is null) and is registered unconditionally; refactoring that moves hook creation behind a nullable factory.","solutions":["Guard before registering: only call addShutdownHook when the Runnable is non-null.","Fix the upstream factory/bean so it returns a no-op hook instead of null.","Log-and-skip null hooks in wrapper code if registration is best-effort."],"exampleFix":"// before\nmanager.addShutdownHook(buildHook()); // may return null\n// after\nRunnable hook = buildHook();\nif (hook != null) {\n    manager.addShutdownHook(hook);\n}","handlingStrategy":"type-guard","validationCode":"if (hook == null) {\n    return; // skip registration of absent cleanup\n}","typeGuard":"void safeAddHook(ShutdownHookManager mgr, Runnable hook) {\n    Objects.requireNonNullElse(hook, Runnable {}); // or skip when null\n    if (hook != null) mgr.addShutdownHook(hook);\n}","tryCatchPattern":"try {\n    manager.addShutdownHook(hook);\n} catch (IllegalArgumentException e) {\n    LOGGER.warn(\"skipped null shutdown hook: {}\", e.getMessage());\n}","preventionTips":["Never pass factory results that can return null directly to addShutdownHook.","Return no-op Runnables from hook factories instead of null.","Centralize hook registration in one guarded helper."],"tags":["shutdown","null-argument","lifecycle"],"backgroundTag":"null-argument","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"}