apache/hadoop · error · IllegalArgumentException

shutdownHook cannot be NULL

Error message

shutdownHook cannot be NULL

What it means

ShutdownHookManager is Hadoop's prioritized, timeout-capable replacement for Runtime.addShutdownHook. addShutdownHook(Runnable, int) rejects a null hook with IllegalArgumentException before touching the hook registry. The hook object was never constructed — usually a factory, DI field, or optional component that produced null.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/ShutdownHookManager.java:298

        return o2.priority - o1.priority;
      }
    });
    return list;
  }

  /**
   * 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.
   */
  @InterfaceAudience.Public
  @InterfaceStability.Stable
  public void addShutdownHook(Runnable shutdownHook, int priority) {
    if (shutdownHook == null) {
      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, priority));
  }

  /**
   *
   * Adds a shutdownHook with a priority and timeout the higher the priority
   * the earlier will run. ShutdownHooks with same priority run
   * in a non-deterministic order. The shutdown hook will be terminated if it
   * has not been finished in the specified period of time.
   *
   * @param shutdownHook shutdownHook <code>Runnable</code>
   * @param priority priority of the shutdownHook
   * @param timeout timeout of the shutdownHook

View on GitHub (pinned to 2add963021)

Solutions

  1. Find who passes null: check the argument expression at the call site
  2. Construct the Runnable before registering, or skip registration entirely when the component is disabled
  3. Add Objects.requireNonNull(hook, "shutdownHook") at your own call boundary for a clearer failure
  4. If the component may legitimately be absent, branch: if (cleanup != null) manager.addShutdownHook(cleanup, prio);

Example fix

// before
ShutdownHookManager.get().addShutdownHook(cleanupTask, 50); // cleanupTask null when init failed

// after
if (cleanupTask != null) {
  ShutdownHookManager.get().addShutdownHook(cleanupTask, 50);
}
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(hook, "shutdownHook must be constructed before registration");
ShutdownHookManager.get().addShutdownHook(hook, priority);

Try / catch

try { ShutdownHookManager.get().addShutdownHook(hook, priority); } catch (IllegalArgumentException e) { /* hook was null: fix construction, skip registration */ }

Prevention

When it happens

Trigger: ShutdownHookManager.get().addShutdownHook(null, priority) — typically hook built lazily (e.g. hook = service != null ? service.newCleanup() : null) and the guard branch lost.

Common situations: Registering cleanup for a service whose initialization failed earlier; optional plugins disabled via config injecting null; test wiring that forgot to instantiate the hook runnable.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/395a0552f66d3bb2. Report an issue: GitHub.