hashicorp/nomad · error
s3_timeout must be > 0
Error message
s3_timeout must be > 0
What it means
Validate() rejects negative s3_timeout values: after nil and parse checks succeed, `v < 0` triggers 's3_timeout must be > 0'. Despite the message wording, the comparison accepts zero; only strictly negative durations fail.
Source
Thrown at nomad/structs/config/artifact.go:217
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)
}
if a.DecompressionSizeLimit == nil {
return fmt.Errorf("decompression_size_limit must not be nil")
}
if v, err := humanize.ParseBytes(*a.DecompressionSizeLimit); err != nil {
return fmt.Errorf("decompression_size_limit is not a valid size: %w", err)
} else if v > math.MaxInt64 {
return fmt.Errorf("decompression_size_limit must be < %d but found %d", int64(math.MaxInt64), v)
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Set s3_timeout to a non-negative duration, e.g. s3_timeout = "30m".
- Omit the field and let DefaultArtifactConfig() provide the default S3 timeout.
- Clamp the value at generation time: if d < 0 { d = defaultS3Timeout }.
Example fix
// before
artifact {
s3_timeout = "-1h"
}
// after
artifact {
s3_timeout = "1h"
} Defensive patterns
Strategy: validation
Validate before calling
d, err := time.ParseDuration(cfg.S3Timeout)
if err != nil || d < 0 {
return fmt.Errorf("s3_timeout must be a non-negative duration, got %q", cfg.S3Timeout)
} Type guard
func validS3Timeout(a *ArtifactConfig) bool {
if a.S3Timeout == nil { return false }
d, err := time.ParseDuration(*a.S3Timeout)
return err == nil && d >= 0
} Prevention
- Use zero or omit the field instead of negative values for 'no limit' semantics.
- Clamp computed durations before serializing config.
- Review templated configs that do duration arithmetic.
When it happens
Trigger: Calling ArtifactConfig.Validate() when *a.S3Timeout parses successfully as a negative duration, e.g. "-1m", "-30s", or "-500ms".
Common situations: Configs where a negative value was intended to mean 'unlimited' or 'disabled'; arithmetic on durations producing negatives; copy/paste of a value including a minus sign; CI scripts interpolating negative default offsets.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- hg_timeout must be > 0
- s3_timeout must be set
- s3_timeout not a valid duration: %w
- failed to parse config:
- rpc.dial_timeout must be greater than or equal to zero
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/ac7c7c52ae848f49.
Report an issue: GitHub.