{"record":{"id":"6a62f3beea801e49","repo":"hashicorp/nomad","slug":"cannot-prepare-consul-tokens-no-task-specified","errorCode":null,"errorMessage":"cannot prepare consul tokens, no task specified","messagePattern":"cannot prepare consul tokens, no task specified","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/consul_hook.go","lineNumber":137,"sourceCode":"\n\tif err := mErr.ErrorOrNil(); err != nil {\n\t\trevokeErr := h.revokeTokens(tokens)\n\t\tmErr = multierror.Append(mErr, revokeErr)\n\t\treturn mErr.ErrorOrNil()\n\t}\n\n\t// write the tokens to hookResources\n\tif err := h.resourcesBackend.setConsulTokens(tokens); err != nil {\n\t\th.logger.Error(\"unable to update tokens in state\", \"error\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (h *consulHook) prepareConsulTokensForTask(task *structs.Task, tg *structs.TaskGroup, tokens map[string]map[string]*consulapi.ACLToken) error {\n\tif task == nil {\n\t\t// programming error\n\t\treturn fmt.Errorf(\"cannot prepare consul tokens, no task specified\")\n\t}\n\n\tclusterName := task.GetConsulClusterName(tg)\n\tconsulConfig, ok := h.consulConfigs[clusterName]\n\tif !ok {\n\t\treturn fmt.Errorf(\"no such consul cluster: %s\", clusterName)\n\t}\n\n\t// Find task workload identity for Consul.\n\twidName := fmt.Sprintf(\"%s_%s\", structs.ConsulTaskIdentityNamePrefix, consulConfig.Name)\n\twid := task.GetIdentity(widName)\n\tif wid == nil {\n\t\t// Skip task if it doesn't have an identity for Consul since it doesn't\n\t\t// need a token.\n\t\treturn nil\n\t}\n\n\ttokenName := widName + \"/\" + task.Name","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/consul_hook.go#L119-L155","documentation":"This error is returned by consulHook.prepareConsulTokensForTask when the *structs.Task argument is nil. The code explicitly comments it as a programming error: Prerun always iterates over non-nil tasks from the task group, so a nil task means an internal caller bug, not a user configuration problem.","triggerScenarios":"Prerun (or another caller) invokes prepareConsulTokensForTask with a nil task pointer, e.g. iterating a task list containing nil entries or passing the result of a failed lookup without checking.","commonSituations":"Seen only during Nomad development, custom forks/patches to allocrunner, or a corrupted task-group lookup returning nil that isn't checked before calling the hook.","solutions":["Check the caller (Prerun in consul_hook.go) to find why a nil task is passed; fix the missing nil check upstream","Report it as a Nomad bug with the agent log and job spec if hit on a stock build","Re-run the allocation; if it persists across restarts, capture a goroutine dump and file an issue"],"exampleFix":"// before\nif err := h.prepareConsulTokensForTask(task, tg, tokens); err != nil { ... }\n// after\nif task != nil {\n    if err := h.prepareConsulTokensForTask(task, tg, tokens); err != nil { ... }\n}","handlingStrategy":"validation","validationCode":"if task == nil {\n    return fmt.Errorf(\"skip: nil task passed to prepareConsulTokensForTask\")\n}\n// otherwise proceed to call the hook\nerr := h.prepareConsulTokensForTask(task, tg, tokens)","typeGuard":"func taskNotNil(t *structs.Task) bool { return t != nil }","tryCatchPattern":null,"preventionTips":["Always nil-check task pointers before passing into allocrunner hooks","Treat this error as a bug: capture stack trace when it occurs","Add unit tests covering hook invocations with all tasks from the task group"],"tags":["nomad","consul","programming-error","nil-pointer"],"backgroundTag":"nil-argument-programming-error","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"}