{"record":{"id":"e0d7353a33e0ad45","repo":"hashicorp/nomad","slug":"nomad-job-templates-is-a-reserved-directory-path","errorCode":null,"errorMessage":"\"nomad/job-templates\" is a reserved directory path, but you may write variables at the level below it, for example, \"nomad/job-templates/template-name\"","messagePattern":"\"nomad/job-templates\" is a reserved directory path, but you may write variables at the level below it, for example, \"nomad/job-templates/template-name\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/variables.go","lineNumber":441,"sourceCode":"\tif parts[0] != \"nomad\" {\n\t\treturn nil\n\t}\n\n\t// Don't allow a variable with path \"nomad\"\n\tif len(parts) == 1 {\n\t\treturn fmt.Errorf(`\"nomad\" is a reserved top-level directory path, but you may write variables to \"nomad/jobs\", \"nomad/job-templates\", \"nomad/sentinel\", or below`)\n\t}\n\n\tswitch {\n\tcase parts[1] == \"jobs\" || parts[1] == \"sentinel\":\n\t\t// Any path including \"nomad/jobs\" or \"nomad/sentinel\" is valid\n\t\treturn nil\n\tcase parts[1] == \"job-templates\" && len(parts) == 3:\n\t\t// Paths including \"nomad/job-templates\" is valid, provided they have single further path part\n\t\treturn nil\n\tcase parts[1] == \"job-templates\":\n\t\t// Disallow exactly nomad/job-templates with no further paths\n\t\treturn fmt.Errorf(\"\\\"nomad/job-templates\\\" is a reserved directory path, but you may write variables at the level below it, for example, \\\"nomad/job-templates/template-name\\\"\")\n\tdefault:\n\t\t// Disallow arbitrary sub-paths beneath nomad/\n\t\treturn fmt.Errorf(\"only paths at \\\"nomad/jobs\\\" or \\\"nomad/job-templates\\\" and below are valid paths under the top-level \\\"nomad\\\" directory\")\n\t}\n}\n\nfunc (vd *VariableDecrypted) Canonicalize() {\n\tif vd.Namespace == \"\" {\n\t\tvd.Namespace = DefaultNamespace\n\t}\n\n\tif vd.Lock != nil {\n\t\tvd.Lock.Canonicalize()\n\t}\n}\n\n// Copy returns a fully hydrated copy of VariableMetadata that can be\n// manipulated while ensuring the original is not touched.","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/variables.go#L423-L459","documentation":"ValidatePath guard: the path is exactly \"nomad/job-templates\" or otherwise not one level deeper. Job templates are addressed as nomad/job-templates/<template-name>, with exactly one further path part.","triggerScenarios":"Thrown at nomad/structs/variables.go:441 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Append the template name, e.g. \"nomad/job-templates/my-template\"","Use exactly one additional path segment below nomad/job-templates"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}