hashicorp/nomad · error
Job ID contains a null character
Error message
Job ID contains a null character
What it means
Job.Validate() rejects Job IDs containing a NUL byte ("\000"). NUL characters can corrupt string handling in downstream systems (logging, raft storage, C strings), so the validator explicitly disallows them. This check runs only after the empty-ID check passes.
Source
Thrown at nomad/structs/structs.go:4748
nj.Periodic = j.Periodic.Copy()
nj.Meta = maps.Clone(j.Meta)
nj.ParameterizedJob = j.ParameterizedJob.Copy()
return nj
}
// Validate is used to check a job for reasonable configuration
func (j *Job) Validate() error {
var mErr multierror.Error
if j.Region == "" && j.Multiregion == nil {
mErr.Errors = append(mErr.Errors, errors.New("Missing job region"))
}
if j.ID == "" {
mErr.Errors = append(mErr.Errors, errors.New("Missing job ID"))
} else if strings.Contains(j.ID, " ") {
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() {View on GitHub (pinned to 482b49bf1a)
Solutions
- Strip NUL bytes from the ID before submission: strings.ReplaceAll(id, "\x00", "")
- Validate input at the boundary with a regex like ^[^\x00]+$
- Inspect the raw bytes of the ID (fmt.Sprintf("%q", id)) to find hidden control characters
Example fix
// before job.ID = rawID // after job.ID = strings.ReplaceAll(rawID, "\x00", "")
Defensive patterns
Strategy: validation
Validate before calling
if strings.Contains(j.ID, "\x00") {
return fmt.Errorf("job ID contains a null character")
} Type guard
func isNulFree(s string) bool { return !strings.ContainsRune(s, '\x00') } Try / catch
if err := job.Validate(); err != nil {
if strings.Contains(err.Error(), "null character") {
job.ID = strings.Map(func(r rune) rune { if r == 0 { return -1 }; return r }, job.ID)
}
} Prevention
- Sanitize all externally supplied job identifiers at your API boundary
- Reject control characters with a regex like ^[^\x00\x1f]+$
- Inspect suspicious strings with %q formatting to reveal hidden bytes
When it happens
Trigger: Submitting a job whose `id` contains an embedded null byte — typically via programmatic construction (j.ID = "job\x00suffix") or deserialized input containing NUL; direct calls to Job.Validate() in Go.
Common situations: Parsing binary or legacy encodings into strings that introduce NULs; string truncation bugs from C interop leaving trailing NULs; malicious or corrupted input from untrusted sources.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Job Name contains a null character
- Missing job ID
- Job ID contains a space
- Missing job name
- Job must be in a namespace
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/80c898227c4d0cc6.
Report an issue: GitHub.