hashicorp/nomad · error
hg_timeout must be > 0
Error message
hg_timeout must be > 0
What it means
Nomad's ArtifactConfig.Validate requires hg_timeout to be set and rejects negative durations. A negative value passed the nil and ParseDuration checks but failed the `v < 0` comparison, so the Mercurial artifact-download timeout is invalid. Only zero and positive durations are accepted (zero meaning no explicit timeout beyond defaults).
Source
Thrown at nomad/structs/config/artifact.go:208
return fmt.Errorf("gcs_timeout must be > 0")
}
if a.GitTimeout == nil {
return fmt.Errorf("git_timeout must be set")
}
if v, err := time.ParseDuration(*a.GitTimeout); err != nil {
return fmt.Errorf("git_timeout not a valid duration: %w", err)
} else if v < 0 {
return fmt.Errorf("git_timeout must be > 0")
}
if a.HgTimeout == nil {
return fmt.Errorf("hg_timeout must be set")
}
if v, err := time.ParseDuration(*a.HgTimeout); err != nil {
return fmt.Errorf("hg_timeout not a valid duration: %w", err)
} else if v < 0 {
return fmt.Errorf("hg_timeout must be > 0")
}
if a.S3Timeout == nil {
return fmt.Errorf("s3_timeout must be set")
}
if v, err := time.ParseDuration(*a.S3Timeout); err != nil {
return fmt.Errorf("s3_timeout not a valid duration: %w", err)
} else if v < 0 {
return fmt.Errorf("s3_timeout must be > 0")
}
if a.DecompressionFileCountLimit == nil {
return fmt.Errorf("decompression_file_count_limit must not be nil")
}
if v := *a.DecompressionFileCountLimit; v < 0 {
return fmt.Errorf("decompression_file_count_limit must be >= 0 but found %d", v)
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Change hg_timeout in the artifact block to a positive duration, e.g. hg_timeout = "30m".
- Remove the explicit hg_timeout so DefaultArtifactConfig() supplies a valid default.
- If hg_timeout is computed from a variable, clamp it with a max(0, v) or abs() before formatting the duration string.
Example fix
// before
artifact {
hg_timeout = "-30s"
}
// after
artifact {
hg_timeout = "30s"
} Defensive patterns
Strategy: validation
Validate before calling
d, err := time.ParseDuration(cfg.HgTimeout)
if err != nil || d < 0 {
return fmt.Errorf("hg_timeout must be a non-negative Go duration, got %q", cfg.HgTimeout)
} Type guard
func validHgTimeout(a *ArtifactConfig) bool {
if a.HgTimeout == nil { return false }
d, err := time.ParseDuration(*a.HgTimeout)
return err == nil && d >= 0
} Prevention
- Never use negative durations to mean 'unlimited' in Nomad configs.
- Unit-test config builders against ArtifactConfig.Validate().
- Run `nomad agent config validate` (or job validate) before deploying config changes.
When it happens
Trigger: Calling ArtifactConfig.Validate() when a.HgTimeout is a non-nil pointer to a duration string that time.ParseDuration accepts but is negative, e.g. *a.HgTimeout == "-30s" or "-5m".
Common situations: Hand-written client or agent hcl/json artifact blocks where a minus sign was typed accidentally; templated config that interpolates a negative computed offset; config copied from tooling that treats -1 as 'disable timeout' (Nomad does not).
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- s3_timeout must be > 0
- failed to parse config:
- rpc.dial_timeout must be greater than or equal to zero
- telemetry in-memory collection interval must be greater than
- telemetry in-memory retention period must be greater than ze
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/67f59256da245f6a.
Report an issue: GitHub.