hashicorp/nomad · error

update hook %q failed: %v

Error message

update hook %q failed: %v

What it means

When an allocation receives an update, each hook's Update(req) is invoked; errors are accumulated (not aborting the first) into a multierror as "update hook \"<name>\" failed: <cause>". This means a hook could not apply the updated alloc (e.g. task group change) — the alloc update is degraded.

Source

Thrown at client/allocrunner/alloc_runner_hooks.go:247

		AllocEnv: allocEnv,
	}

	var merr multierror.Error
	for _, hook := range ar.runnerHooks {
		h, ok := hook.(interfaces.RunnerUpdateHook)
		if !ok {
			continue
		}

		name := h.Name()
		var start time.Time
		if ar.logger.IsTrace() {
			start = time.Now()
			ar.logger.Trace("running update hook", "name", name, "start", start)
		}

		if err := h.Update(req); err != nil {
			merr.Errors = append(merr.Errors, fmt.Errorf("update hook %q failed: %v", name, err))
		}

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

	return merr.ErrorOrNil()
}

// postrun is used to run the runners postrun hooks.
// all hooks will run, even if any of them fail, and return a multierror, single error, or nil.
func (ar *allocRunner) postrun() error {
	if ar.logger.IsTrace() {
		start := time.Now()
		ar.logger.Trace("running post-run hooks", "start", start)
		defer func() {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the hook name and wrapped cause from the aggregated multierror (alloc runner logs include it)
  2. Check whether the new task version's image/artifact is pullable; fix and trigger another deployment
  3. Verify Consul service/registration configuration if a service hook failed
  4. Re-run the deployment or restart the alloc (nomad alloc restart / job stop-start) to re-apply the update
Defensive patterns

Strategy: retry

Validate before calling

alloc, _, err := client.Allocations().Info(ctx, allocID, nil)
if err == nil {
  for _, e := range alloc.TaskEvents {
    if e.DisplayMessage != "" { log.Printf("alloc event: %s", e.DisplayMessage) }
  }
}

Try / catch

if err := triggerUpdate(allocID, desired); err != nil {
  if isHookUpdateFailure(err) { // multierror containing "update hook" text
    time.Sleep(backoff); return triggerUpdate(allocID, desired) // idempotent re-apply
  }
}

Prevention

When it happens

Trigger: handleAllocUpdate → update runs on alloc change; any hook whose Update errors, e.g. task runner update failing to adjust resources, service hook failing to re-register checks, or script check hooks failing.

Common situations: In-place deployment where a task can't be updated (image pull error on new version); Consul/Nomad service registration failure during service update; volatile environment (network blip) during update; resource change rejected by driver.

Related errors


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