{"record":{"id":"69267c8956025f56","repo":"hashicorp/nomad","slug":"poststart-hook-q-failed-v","errorCode":null,"errorMessage":"poststart hook %q failed: %v","messagePattern":"poststart hook %q failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/task_runner_hooks.go","lineNumber":392,"sourceCode":"\t\t}\n\n\t\tname := post.Name()\n\t\tvar start time.Time\n\t\tif tr.logger.IsTrace() {\n\t\t\tstart = time.Now()\n\t\t\ttr.logger.Trace(\"running poststart hook\", \"name\", name, \"start\", start)\n\t\t}\n\n\t\treq := interfaces.TaskPoststartRequest{\n\t\t\tDriverExec:    lazyHandle,\n\t\t\tDriverNetwork: net,\n\t\t\tDriverStats:   lazyHandle,\n\t\t\tTaskEnv:       tr.envBuilder.Build(),\n\t\t}\n\t\tvar resp interfaces.TaskPoststartResponse\n\t\tif err := post.Poststart(tr.killCtx, &req, &resp); err != nil {\n\t\t\ttr.emitHookError(err, name)\n\t\t\tmerr.Errors = append(merr.Errors, fmt.Errorf(\"poststart hook %q failed: %v\", name, err))\n\t\t}\n\n\t\t// No need to persist as PoststartResponse is currently empty\n\n\t\tif tr.logger.IsTrace() {\n\t\t\tend := time.Now()\n\t\t\ttr.logger.Trace(\"finished poststart hooks\", \"name\", name, \"end\", end, \"duration\", end.Sub(start))\n\t\t}\n\t}\n\n\treturn merr.ErrorOrNil()\n}\n\n// exited is used to run the exited hooks before a task is stopped.\nfunc (tr *TaskRunner) exited() error {\n\tif tr.logger.IsTrace() {\n\t\tstart := time.Now()\n\t\ttr.logger.Trace(\"running exited hooks\", \"start\", start)","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/task_runner_hooks.go#L374-L410","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the wrapped inner error in the log line to identify which hook and root cause failed","Check the task's driver configuration in the job spec for invalid fields consumed by the failing hook","Verify external dependencies used by the hook (Consul, Vault, driver service endpoints) are reachable from the client","Restart the allocation (nomad alloc restart / stop-reschedule) once the underlying cause is fixed","If caused by a driver plugin, check plugin logs and ensure plugin and Nomad versions are compatible"],"exampleFix":"// before: task with bad poststart hook input\ntask \"app\" {\n  driver = \"docker\"\n  # service block referencing a nonexistent Consul namespace\n}\n\n// after: corrected service config\nservice {\n  name     = \"app\"\n  provider = \"consul\"\n  # valid namespace configured\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Go: caller of taskrunner.Run inspects the returned multierror\nif err := tr.Run(); err != nil {\n    var hookErr *multierror.Error\n    if errors.As(err, &hookErr) {\n        for _, e := range hookErr.Errors {\n            if strings.Contains(e.Error(), \"poststart hook\") {\n                logger.Error(\"poststart hook failed\", \"err\", e)\n                // retry or reschedule the allocation\n            }\n        }\n    }\n}","preventionTips":["Validate all hook-related task config (services, script checks, driver fields) with nomad job validate before submitting","Keep Consul/Vault and driver plugins reachable and version-compatible with the Nomad client","Monitor alloc events for poststart failures and alert on repeated occurrences","Pin and test driver plugin versions alongside Nomad upgrades"],"tags":["nomad","task-runner","hooks","poststart"],"backgroundTag":"task-lifecycle-hook-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}