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

  1. Set s3_timeout to a non-negative duration, e.g. s3_timeout = "30m".
  2. Omit the field and let DefaultArtifactConfig() provide the default S3 timeout.
  3. 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

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

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/ac7c7c52ae848f49. Report an issue: GitHub.