{"record":{"id":"19ddbd6dba03e786","repo":"hashicorp/nomad","slug":"all-templates-should-have-same-once-value","errorCode":null,"errorMessage":"All templates should have same Once value","messagePattern":"All templates should have same Once value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/template/template.go","lineNumber":176,"sourceCode":"\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\n}\n\nfunc (c *TaskTemplateManagerConfig) OnceModeEnabled() bool {\n\treturn len(c.Templates) > 0 && c.Templates[0].Once\n}\n\nfunc NewTaskTemplateManager(config *TaskTemplateManagerConfig) (*TaskTemplateManager, error) {\n\t// Check pre-conditions\n\tif err := config.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\ttm := &TaskTemplateManager{\n\t\tconfig:     config,","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/template/template.go#L158-L194","documentation":"Validate() enforces that every template in c.Templates has the same value for the Once field, because Once is conceptually a runner-level setting in consul-template but Nomad sets it per template. Mixed values are ambiguous, so the config is rejected.","triggerScenarios":"Calling NewTaskTemplateManager with a Templates slice where at least one template block has `once = true` while another has `once = false` (or is unset, defaulting to false).","commonSituations":"A Nomad job spec where only some `template` stanzas in the same task set `once = true`; programmatic template generation that toggles Once per template.","solutions":["Make all template stanzas in the task agree on `once`: either add `once = true` to every template or remove it from all.","If only one template needs one-shot rendering, split it into a separate task (each task gets its own template manager).","Programmatically, normalize t.Once across the slice before constructing the manager."],"exampleFix":"// before (job HCL)\ntemplate { data = \"a\"; once = true  }\ntemplate { data = \"b\" }\n// after\ntemplate { data = \"a\"; once = true }\ntemplate { data = \"b\"; once = true }","handlingStrategy":"validation","validationCode":"var once *bool\nfor i := range cfg.Templates {\n    v := cfg.Templates[i].Once\n    if once == nil { once = &v } else if v != *once {\n        return fmt.Errorf(\"all templates must agree on `once`\")\n    }\n}","typeGuard":null,"tryCatchPattern":"tm, err := template.NewTaskTemplateManager(cfg)\nif err != nil {\n    return fmt.Errorf(\"creating template manager: %w\", err)\n}","preventionTips":["Normalize the Once field across templates before constructing the manager.","Validate job specs (HCL/JSON) so all template stanzas in a task share the same `once` value.","If per-template one-shot rendering is needed, use separate tasks."],"tags":["config","validation","nomad","template","consul-template"],"backgroundTag":"inconsistent-configuration","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"}