{"record":{"id":"9d8ea5b9faff6cdd","repo":"hashicorp/nomad","slug":"missing-job-id","errorCode":null,"errorMessage":"Missing job ID","messagePattern":"Missing job ID","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":4744,"sourceCode":"\t\t}\n\t\tnj.TaskGroups = tgs\n\t}\n\n\tnj.Periodic = j.Periodic.Copy()\n\tnj.Meta = maps.Clone(j.Meta)\n\tnj.ParameterizedJob = j.ParameterizedJob.Copy()\n\treturn nj\n}\n\n// Validate is used to check a job for reasonable configuration\nfunc (j *Job) Validate() error {\n\tvar mErr multierror.Error\n\n\tif j.Region == \"\" && j.Multiregion == nil {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing job region\"))\n\t}\n\tif j.ID == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing job ID\"))\n\t} else if strings.Contains(j.ID, \" \") {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Job ID contains a space\"))\n\t} else if strings.Contains(j.ID, \"\\000\") {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Job ID contains a null character\"))\n\t}\n\tif j.Name == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing job name\"))\n\t} else if strings.Contains(j.Name, \"\\000\") {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Job Name contains a null character\"))\n\t}\n\n\tif j.Namespace == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Job must be in a namespace\"))\n\t}\n\tswitch j.Type {\n\tcase JobTypeCore, JobTypeService, JobTypeBatch, JobTypeSystem, JobTypeSysBatch:\n\tcase \"\":\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing job type\"))","sourceCodeStart":4726,"sourceCodeEnd":4762,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L4726-L4762","documentation":"This error comes from the Job.Validate() method in HashiCorp Nomad's structs package. It is appended to a multierror when a submitted Job spec has an empty ID field. The Job ID is the primary identifier used by the Nomad scheduler and API to track the job, so it is mandatory.","triggerScenarios":"Calling the Nomad HTTP API (POST /v1/jobs) or nomad job run with a job HCL/JSON whose top-level 'id' (or 'name' when id is omitted and not defaulted) is the empty string, or constructing a structs.Job in Go and calling Validate() with j.ID == \"\".","commonSituations":"HCL job files that set only 'name' while templating produces an empty id field; programmatic job generation where the ID template variable renders empty; accidentally passing an empty string to a job struct in Go code.","solutions":["Set an explicit `id` field in your job HCL/JSON, e.g. `id = \"my-app\"`","If relying on the default, ensure the job `name` is set so Nomad can derive an ID (jobs submitted via /v1/jobs default ID to name server-side only in some paths — set both explicitly)","When building jobs programmatically, assign job.ID before calling Validate() or the register endpoint"],"exampleFix":"// before\njob \"\" {\n  ...\n}\n// after\njob \"web-app\" {\n  ...\n}","handlingStrategy":"validation","validationCode":"if j.ID == \"\" {\n    return fmt.Errorf(\"job ID must be set before submission\")\n}","typeGuard":"func hasJobID(j *structs.Job) bool { return j != nil && j.ID != \"\" }","tryCatchPattern":"if err := job.Validate(); err != nil {\n    var mErr multierror.Error\n    if errors.As(err, &mErr) {\n        for _, e := range mErr.Errors {\n            if strings.Contains(e.Error(), \"Missing job ID\") { /* fix ID */ }\n        }\n    }\n}","preventionTips":["Always set both id and name in job HCL files","Lint job files with `nomad job validate` before submitting","Add CI checks that reject templated IDs resolving to empty strings"],"tags":["nomad","go","validation","job-spec"],"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"}