hashicorp/nomad · error

poststart hook %q failed: %v

Error message

poststart hook %q failed: %v

What it means

This error wraps a failure from a task driver's poststart hook, which runs after a task's driver has started it and returned a handle. Nomad calls Poststart on each registered hook (via the hook's Poststart method) during task Run; if any hook returns an error, Nomad records it via emitHookError and accumulates it in a multierror with this message. The wrapped error (%v) comes from the specific hook implementation (e.g. driver script checks, Consul/Vault setup), so the root cause is in the inner text.

Source

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

		}

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

		req := interfaces.TaskPoststartRequest{
			DriverExec:    lazyHandle,
			DriverNetwork: net,
			DriverStats:   lazyHandle,
			TaskEnv:       tr.envBuilder.Build(),
		}
		var resp interfaces.TaskPoststartResponse
		if err := post.Poststart(tr.killCtx, &req, &resp); err != nil {
			tr.emitHookError(err, name)
			merr.Errors = append(merr.Errors, fmt.Errorf("poststart hook %q failed: %v", name, err))
		}

		// No need to persist as PoststartResponse is currently empty

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

	return merr.ErrorOrNil()
}

// exited is used to run the exited hooks before a task is stopped.
func (tr *TaskRunner) exited() error {
	if tr.logger.IsTrace() {
		start := time.Now()
		tr.logger.Trace("running exited hooks", "start", start)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the wrapped inner error in the log line to identify which hook and root cause failed
  2. Check the task's driver configuration in the job spec for invalid fields consumed by the failing hook
  3. Verify external dependencies used by the hook (Consul, Vault, driver service endpoints) are reachable from the client
  4. Restart the allocation (nomad alloc restart / stop-reschedule) once the underlying cause is fixed
  5. If caused by a driver plugin, check plugin logs and ensure plugin and Nomad versions are compatible

Example fix

// before: task with bad poststart hook input
task "app" {
  driver = "docker"
  # service block referencing a nonexistent Consul namespace
}

// after: corrected service config
service {
  name     = "app"
  provider = "consul"
  # valid namespace configured
}
Defensive patterns

Strategy: try-catch

Try / catch

// Go: caller of taskrunner.Run inspects the returned multierror
if err := tr.Run(); err != nil {
    var hookErr *multierror.Error
    if errors.As(err, &hookErr) {
        for _, e := range hookErr.Errors {
            if strings.Contains(e.Error(), "poststart hook") {
                logger.Error("poststart hook failed", "err", e)
                // retry or reschedule the allocation
            }
        }
    }
}

Prevention

When it happens

Trigger: A poststart hook's Poststart(ctx, req, resp) call returns a non-nil error during taskrunner Run — e.g. a driver post-start step fails (script check registration, remote task handle operations) or a plugin hook returns an error response.

Common situations: Driver plugins whose Poststart does remote work failing due to connectivity issues; misconfigured task fields consumed by poststart hooks (bad script_check args, missing service definitions); driver version mismatches after Nomad upgrades where the hook protocol behaves differently; transient failures right after task start.

Related errors


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