apache/shenyu · error · IllegalArgumentException
shutdownHook cannot be NULL
Error message
shutdownHook cannot be NULL
What it means
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.
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.
Example fix
// before
manager.addShutdownHook(buildHook()); // may return null
// after
Runnable hook = buildHook();
if (hook != null) {
manager.addShutdownHook(hook);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (hook == null) {
return; // skip registration of absent cleanup
} Type guard
void safeAddHook(ShutdownHookManager mgr, Runnable hook) {
Objects.requireNonNullElse(hook, Runnable {}); // or skip when null
if (hook != null) mgr.addShutdownHook(hook);
} Try / catch
try {
manager.addShutdownHook(hook);
} catch (IllegalArgumentException e) {
LOGGER.warn("skipped null shutdown hook: {}", e.getMessage());
} Prevention
- 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.
When it happens
Trigger: Calling ShutdownHookManager.getInstance().addShutdownHook(null), typically when a hook variable comes from an unset config/optional bean or a failed initialization returns null.
Common situations: 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.
Related errors
- Shutdown in progress, cannot add a shutdownHook
- Shutdown in progress, cannot remove a shutdownHook
- Executor is shutdown!
- namespaceId can not be null
- namespace is not exist
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/e8e8836651a48bff.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/shutdown/ShutdownHookManager.java:102
synchronized (MGR.hooks) {
list = new ArrayList<>(MGR.hooks);
}
list.sort((o1, o2) -> o2.priority - o1.priority);
List<Runnable> ordered = new ArrayList<>();
list.forEach(entry -> ordered.add(entry.hook));
return ordered;
}
/**
* Adds a shutdownHook with default priority zero, the higher the priority
* the earlier will run. ShutdownHooks with same priority run
* in a non-deterministic order.
*
* @param shutdownHook shutdownHook <code>Runnable</code>
*/
public void addShutdownHook(final Runnable shutdownHook) {
if (Objects.isNull(shutdownHook)) {
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, 0));
}
/**
* 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.
*/
public void addShutdownHook(final Runnable shutdownHook, final int priority) {
if (Objects.isNull(shutdownHook)) {
throw new IllegalArgumentException("shutdownHook cannot be NULL");View on GitHub (pinned to 567142e072)