hashicorp/nomad · warning

exited hook %q failed: %v

Error message

exited hook %q failed: %v

What it means

This error wraps a failure from a task's exited hook, invoked after the task has finished running. During taskrunner Run teardown, each registered hook's Exited method is called with an empty TaskExitedRequest; a non-nil error is logged via emitHookError and accumulated in a multierror with this message. Since TaskExitedResponse is empty and not persisted, the failure affects cleanup/telemetry rather than task state.

Source

Thrown at client/allocrunner/taskrunner/task_runner_hooks.go:435

	var merr multierror.Error
	for _, hook := range tr.runnerHooks {
		post, ok := hook.(interfaces.TaskExitedHook)
		if !ok {
			continue
		}

		name := post.Name()
		var start time.Time
		if tr.logger.IsTrace() {
			start = time.Now()
			tr.logger.Trace("running exited hook", "name", name, "start", start)
		}

		req := interfaces.TaskExitedRequest{}
		var resp interfaces.TaskExitedResponse
		if err := post.Exited(tr.killCtx, &req, &resp); err != nil {
			tr.emitHookError(err, name)
			merr.Errors = append(merr.Errors, fmt.Errorf("exited hook %q failed: %v", name, err))
		}

		// No need to persist as TaskExitedResponse is currently empty

		if tr.logger.IsTrace() {
			end := time.Now()
			tr.logger.Trace("finished exited hooks", "name", name, "end", end, "duration", end.Sub(start))
		}
	}

	return merr.ErrorOrNil()

}

// stop is used to run the stop hooks.
func (tr *TaskRunner) stop() error {
	if tr.logger.IsTrace() {
		start := time.Now()

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the wrapped inner error to find which exited hook failed and why
  2. Check driver/plugin logs for resource cleanup failures after the task exited
  3. Verify external systems the hook talks to (Consul, driver daemons) are healthy
  4. Ensure leftover task resources are cleaned (nomad system gc or restart the client) if cleanup failed
  5. Upgrade or restart the driver plugin if it is crashing during exit handling
Defensive patterns

Strategy: try-catch

Try / catch

// Go: wrap Run and treat exited-hook failures as cleanup warnings
err := tr.Run()
if err != nil && strings.Contains(err.Error(), "exited hook") {
    logger.Warn("exited hook failure during teardown; task state unaffected", "err", err)
    // trigger resource GC or plugin restart as remediation
}

Prevention

When it happens

Trigger: A hook implementing interfaces.TaskExited's Exited(ctx, req, resp) returns an error when the taskrunner processes task exit during Run — e.g. a driver's exit handling fails to release resources or a monitoring hook fails to report task exit.

Common situations: Driver plugins failing to clean up after task termination (leaked processes, failed stats close); hooks contacting external systems (Consul deregistration issues) after task exit; plugin crashes or timeouts triggered by task exit events; failures occurring alongside an already-failing task exit.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/8f1c3df51e944816. Report an issue: GitHub.