hashicorp/nomad · error
Invalid job type: %q
Error message
Invalid job type: %q
What it means
Job.Validate() accepts only the known job types: core, service, batch, system, and sysbatch. An empty type yields 'Missing job type'; any other non-empty string fails with this error. The job type drives scheduler selection, so an unknown value cannot be dispatched.
Source
Thrown at nomad/structs/structs.go:4764
mErr.Errors = append(mErr.Errors, errors.New("Job ID contains a space"))
} else if strings.Contains(j.ID, "\000") {
mErr.Errors = append(mErr.Errors, errors.New("Job ID contains a null character"))
}
if j.Name == "" {
mErr.Errors = append(mErr.Errors, errors.New("Missing job name"))
} else if strings.Contains(j.Name, "\000") {
mErr.Errors = append(mErr.Errors, errors.New("Job Name contains a null character"))
}
if j.Namespace == "" {
mErr.Errors = append(mErr.Errors, errors.New("Job must be in a namespace"))
}
switch j.Type {
case JobTypeCore, JobTypeService, JobTypeBatch, JobTypeSystem, JobTypeSysBatch:
case "":
mErr.Errors = append(mErr.Errors, errors.New("Missing job type"))
default:
mErr.Errors = append(mErr.Errors, fmt.Errorf("Invalid job type: %q", j.Type))
}
if len(j.Datacenters) == 0 && !j.IsMultiregion() {
mErr.Errors = append(mErr.Errors, errors.New("Missing job datacenters"))
} else {
for _, v := range j.Datacenters {
if v == "" {
mErr.Errors = append(mErr.Errors, errors.New("Job datacenter must be non-empty string"))
}
}
}
if len(j.TaskGroups) == 0 {
mErr.Errors = append(mErr.Errors, errors.New("Missing job task groups"))
}
for idx, constr := range j.Constraints {
if err := constr.Validate(); err != nil {
outer := fmt.Errorf("Constraint %d validation failed: %s", idx+1, err)
mErr.Errors = append(mErr.Errors, outer)View on GitHub (pinned to 482b49bf1a)
Solutions
- Set the job type to one of: service, batch, system, or sysbatch (core is reserved for internal use)
- Use a periodic/cron trigger stanza on a batch or service job instead of inventing a 'cron' type
- Validate with nomad job validate to catch typos before submission
Example fix
// before
job "app" {
type = "daemon"
}
// after
job "app" {
type = "service"
} Defensive patterns
Strategy: type-guard
Validate before calling
switch j.Type {
case structs.JobTypeService, structs.JobTypeBatch, structs.JobTypeSystem, structs.JobTypeSysBatch:
// ok
case "":
return errors.New("missing job type")
default:
return fmt.Errorf("invalid job type %q", j.Type)
} Type guard
func validJobType(t string) bool {
switch t {
case structs.JobTypeCore, structs.JobTypeService, structs.JobTypeBatch, structs.JobTypeSystem, structs.JobTypeSysBatch:
return true
}
return false
} Prevention
- Always set type explicitly to service, batch, system, or sysbatch
- Never use 'cron' or 'daemon' types; use periodic triggers on batch/service instead
- Keep job type lowercase exactly as the constants define
- Run nomad job validate in CI before submission
When it happens
Trigger: Submitting a job with type = "daemon", "cron", or any misspelled value (e.g. "Ssystem") via nomad job run or the jobs API.
Common situations: Confusing Nomad job types with other schedulers' terminology (e.g. 'daemon' or 'cron' — periodic jobs are service/batch with a cron trigger); case errors; hand-edited JSON specs.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- <combined HCL diagnostics from str.String()>
- command cannot be empty
- hostname cannot be set on task group using %q networking mod
- Constraint %d validation failed: using unsupported operand %
- Constraint %d validation failed: %s
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/3d9fa4891abc9d26.
Report an issue: GitHub.