{"record":{"id":"fecfe5e1c86619c8","repo":"hashicorp/nomad","slug":"only-paths-at-nomad-jobs-or-nomad-job-templates","errorCode":null,"errorMessage":"only paths at \"nomad/jobs\" or \"nomad/job-templates\" and below are valid paths under the top-level \"nomad\" directory","messagePattern":"only paths at \"nomad/jobs\" or \"nomad/job-templates\" and below are valid paths under the top-level \"nomad\" directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/variables.go","lineNumber":444,"sourceCode":"\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.\nfunc (sv *VariableMetadata) Copy() *VariableMetadata {\n\tif sv == nil {\n\t\treturn nil","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/variables.go#L426-L462","documentation":"ValidatePath catch-all guard: the path falls under the top-level \"nomad\" directory but is not one of the permitted subtrees (nomad/jobs, nomad/sentinel, or nomad/job-templates/<name>), so it is rejected.","triggerScenarios":"Thrown at nomad/structs/variables.go:444 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Move the variable under \"nomad/jobs/\" or \"nomad/job-templates/<name>\"","Use a top-level path outside \"nomad\" for user variables"],"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"}