{"record":{"id":"ff27f19c6dba0645","repo":"hashicorp/nomad","slug":"task-q-not-found-in-updated-alloc","errorCode":null,"errorMessage":"task %q not found in updated alloc","messagePattern":"task %q not found in updated alloc","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/script_check_hook.go","lineNumber":134,"sourceCode":"\t\th.logger.Debug(\"driver doesn't support script checks\")\n\t\treturn nil\n\t}\n\th.driverExec = req.DriverExec\n\th.taskEnv = req.TaskEnv\n\n\treturn h.upsertChecks()\n}\n\n// Updated implements interfaces.TaskUpdateHook. It creates new\n// script checks with the current task context (driver and env and possibly\n// new structs.Task), and starts up the scripts.\nfunc (h *scriptCheckHook) Update(ctx context.Context, req *interfaces.TaskUpdateRequest, _ *interfaces.TaskUpdateResponse) error {\n\th.mu.Lock()\n\tdefer h.mu.Unlock()\n\n\ttask := req.Alloc.LookupTask(h.task.Name)\n\tif task == nil {\n\t\treturn fmt.Errorf(\"task %q not found in updated alloc\", h.task.Name)\n\t}\n\th.alloc = req.Alloc\n\th.task = task\n\th.taskEnv = req.TaskEnv\n\th.groupConsulNamespace = req.Alloc.ConsulNamespace()\n\th.taskConsulNamespace = req.Alloc.ConsulNamespaceForTask(task.Name)\n\n\treturn h.upsertChecks()\n}\n\nfunc (h *scriptCheckHook) upsertChecks() error {\n\t// Create new script checks struct with new task context\n\toldScriptChecks := h.scripts\n\th.scripts = h.newScriptChecks()\n\n\t// Run new or replacement scripts\n\tfor id, script := range h.scripts {\n\t\t// If it's already running, cancel and replace","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/script_check_hook.go#L116-L152","documentation":"scriptCheckHook.Update refreshes the hook's cached alloc, task, env, and Consul namespaces whenever the allocation is updated. It looks up the task by the hook's stored task name using req.Alloc.LookupTask; if the updated allocation no longer contains a task with that name, the update cannot proceed and this error is returned.","triggerScenarios":"An updated allocation (from a job spec change or rescheduling diff) omits or renames the task that this script_check_hook was created for. Update is called by the task runner on alloc updates; LookupTask(h.task.Name) returns nil and Update returns this error without mutating any hook state.","commonSituations":"A `nomad job stop`/job edit removes or renames a task in a group while script checks are attached; a misapplied job spec diff drops a task; tooling that synthesizes modified allocations (tests, diff appliers) produces an alloc missing the task; races where Update arrives for an alloc of a different task version.","solutions":["Ensure updated job specs keep the same task name; if removing a task, let the Stop path (not Update) handle it","Check that the allocation being passed in Update actually corresponds to the same task runner/group","Diff the job before/after (`nomad job inspect`) to find where the task name changed","If writing tooling/tests that mutate allocs, always preserve the task entry that hooks reference"],"exampleFix":"// before\nupdate := &api.Job{Name: &jobName, TaskGroups: []*api.TaskGroup{{Name: &tgName}}} // task dropped\n// after: keep the task entry so Update can find it\nupdate := &api.Job{Name: &jobName, TaskGroups: []*api.TaskGroup{{\n    Name: &tgName,\n    Tasks: append(newTasks, existingTask), // task with script checks preserved\n}}}","handlingStrategy":"validation","validationCode":"// caller-side check before invoking Update\nfunc canUpdate(h *scriptCheckHook, alloc *structs.Allocation) bool {\n    return alloc != nil && alloc.LookupTask(h.task.Name) != nil\n}","typeGuard":"func taskExists(alloc *structs.Allocation, name string) bool {\n    return alloc.LookupTask(name) != nil\n}","tryCatchPattern":"if err := hook.Update(ctx, req, resp); err != nil {\n    if strings.Contains(err.Error(), \"not found in updated alloc\") {\n        // alloc no longer has this task; skip update, rely on Stop\n        return nil\n    }\n    return err\n}","preventionTips":["Keep task names stable across job spec edits; rename via new task group only","Diff job specs before applying to catch dropped tasks","When synthesizing allocations in tests, always include the task under test","Handle removed tasks through the stop path, not by stripping them from Update payloads"],"tags":["nomad","alloc-update","script-check","task-lookup","consul"],"backgroundTag":"task-not-found-in-alloc","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"}