{"record":{"id":"5577618a138cf0a8","repo":"hashicorp/nomad","slug":"invalid-task-directory-given-q","errorCode":null,"errorMessage":"Invalid task directory given: %q","messagePattern":"Invalid task directory given: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/template/template.go","lineNumber":162,"sourceCode":"\t// Nomad custom RenderFunc used for sandboxing. This is currently used by\n\t// the secrets block to hold all templated data in memory.\n\tRenderFunc renderer.Renderer\n}\n\n// Validate validates the configuration.\nfunc (c *TaskTemplateManagerConfig) Validate() error {\n\tif c == nil {\n\t\treturn fmt.Errorf(\"Nil config passed\")\n\t} else if c.UnblockCh == nil {\n\t\treturn fmt.Errorf(\"Invalid unblock channel given\")\n\t} else if c.Lifecycle == nil {\n\t\treturn fmt.Errorf(\"Invalid lifecycle hooks given\")\n\t} else if c.Events == nil {\n\t\treturn fmt.Errorf(\"Invalid event hook given\")\n\t} else if c.ClientConfig == nil {\n\t\treturn fmt.Errorf(\"Invalid client config given\")\n\t} else if c.TaskDir == \"\" {\n\t\treturn fmt.Errorf(\"Invalid task directory given: %q\", c.TaskDir)\n\t} else if c.EnvBuilder == nil {\n\t\treturn fmt.Errorf(\"Invalid task environment given\")\n\t} else if c.MaxTemplateEventRate == 0 {\n\t\treturn fmt.Errorf(\"Invalid max template event rate given\")\n\t}\n\n\t// Once is a runner config, but in Nomad it is set per template, so all\n\t// templates given to a runner should have the same value for Once.\n\tvar once bool\n\tfor i, t := range c.Templates {\n\t\tif i == 0 {\n\t\t\tonce = t.Once\n\t\t} else if t.Once != once {\n\t\t\treturn fmt.Errorf(\"All templates should have same Once value\")\n\t\t}\n\t}\n\n\treturn nil","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/template/template.go#L144-L180","documentation":"TaskTemplateManagerConfig.Validate() rejects the config when c.TaskDir is the empty string. The task directory is required because the template runner renders consul-template outputs into the task's sandbox directory. NewTaskTemplateManager calls Validate as its first step, so a manager can never be created without a TaskDir.","triggerScenarios":"Calling NewTaskTemplateManager with a *TaskTemplateManagerConfig whose TaskDir field was never set (left as \"\"), typically because the caller building the config did not wire in the allocrunner's task directory handle.","commonSituations":"Custom client-side tooling or tests constructing TaskTemplateManagerConfig by hand; refactors of alloc runner code where the task dir is assigned after the template manager is built; mis-ordered initialization in a task runner setup.","solutions":["Set config.TaskDir to the task's directory path before calling NewTaskTemplateManager.","Ensure the alloc dir/task dir is created and its path propagated into the task runner config before template manager construction.","If writing tests, populate TaskDir with a t.TempDir() value in the config fixture."],"exampleFix":"// before\ncfg := &template.TaskTemplateManagerConfig{\n    UnblockCh: ch,\n    Lifecycle: lc,\n    Events: ev,\n    ClientConfig: cc,\n}\n// after\ncfg := &template.TaskTemplateManagerConfig{\n    UnblockCh: ch,\n    Lifecycle: lc,\n    Events: ev,\n    ClientConfig: cc,\n    TaskDir: taskDir, // e.g. filepath.Join(allocDir, taskName)\n}","handlingStrategy":"validation","validationCode":"if cfg == nil || cfg.TaskDir == \"\" {\n    return fmt.Errorf(\"template manager config needs a non-empty TaskDir\")\n}","typeGuard":"func hasTaskDir(c *template.TaskTemplateManagerConfig) bool { return c != nil && c.TaskDir != \"\" }","tryCatchPattern":"tm, err := template.NewTaskTemplateManager(cfg)\nif err != nil {\n    return fmt.Errorf(\"creating template manager: %w\", err)\n}","preventionTips":["Build TaskTemplateManagerConfig through a single constructor that always sets TaskDir from the task directory handle.","Write a unit-test fixture helper that fills all required config fields.","Fail fast at startup with a clear message if the task dir path is empty."],"tags":["config","validation","nomad-client","template"],"backgroundTag":"missing-required-argument","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"}