hashicorp/nomad · error
gcs_timeout not a valid duration: %w
Error message
gcs_timeout not a valid duration: %w
What it means
Returned by ArtifactConfig.Validate when gcs_timeout is set but cannot be parsed by time.ParseDuration as a Go duration string. Valid formats include "300ms", "5m", "1h30m"; the wrapped error pinpoints the invalid syntax.
Source
Thrown at nomad/structs/config/artifact.go:188
return fmt.Errorf("http_read_timeout not a valid duration: %w", err)
} else if v < 0 {
return fmt.Errorf("http_read_timeout must be > 0")
}
if a.HTTPMaxSize == nil {
return fmt.Errorf("http_max_size must be set")
}
if v, err := humanize.ParseBytes(*a.HTTPMaxSize); err != nil {
return fmt.Errorf("http_max_size not a valid size: %w", err)
} else if v > math.MaxInt64 {
return fmt.Errorf("http_max_size must be < %d but found %d", int64(math.MaxInt64), v)
}
if a.GCSTimeout == nil {
return fmt.Errorf("gcs_timeout must be set")
}
if v, err := time.ParseDuration(*a.GCSTimeout); err != nil {
return fmt.Errorf("gcs_timeout not a valid duration: %w", err)
} else if v < 0 {
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)View on GitHub (pinned to 482b49bf1a)
Solutions
- Use a valid Go duration string with a unit suffix, e.g. "5m", "300s", "1h".
- Ensure templated/env-substituted values include the unit (e.g. append "s" for seconds).
- Check the wrapped %w message to find the exact invalid portion of the string.
- Validate the config with `nomad validate` before restarting the agent.
Example fix
// before
artifact {
gcs_timeout = "300"
}
// after
artifact {
gcs_timeout = "300s"
} Defensive patterns
Strategy: validation
Validate before calling
func validDuration(s *string) bool {
if s == nil { return false }
_, err := time.ParseDuration(*s)
return err == nil
} Type guard
func isDuration(s string) bool {
_, err := time.ParseDuration(s)
return err == nil
} Prevention
- Always use Go duration syntax: number + unit (ms, s, m, h).
- Append 's' when substituting raw seconds from env/templating.
- Avoid locale-formatted numbers (no commas or spaces).
- Lint config files with nomad validate before rollout.
When it happens
Trigger: Setting `gcs_timeout` to values like "5" (no unit), "5 minutes" (space and full word), "5m30" (trailing partial), "" (empty), or numeric-only input from environment/templating substitution.
Common situations: Confusing Go duration syntax with seconds-integer conventions used elsewhere; templating injecting an unquoted number; typos such as "300sec" or "5min"; copying values from non-Nomad tools with different duration formats.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- gcs_timeout must be > 0
- git_timeout not a valid duration: %w
- git_timeout must be > 0
- hg_timeout not a valid duration: %w
- wait config is nil or empty
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/b0215417be28cee6.
Report an issue: GitHub.