hashicorp/nomad · error

error parsing GCSTimeout: %w

Error message

error parsing GCSTimeout: %w

What it means

ArtifactConfigFromAgent parses GCSTimeout with time.ParseDuration to produce a time.Duration for GCS artifact downloads. A non-duration string cannot be converted, so the wrapped parse error is returned with this message and the ArtifactConfig is not built.

Source

Thrown at client/config/artifact.go:50

	SetEnvironmentVariables       string
}

// ArtifactConfigFromAgent creates a new internal readonly copy of the client
// agent's ArtifactConfig. The config should have already been validated.
func ArtifactConfigFromAgent(c *config.ArtifactConfig) (*ArtifactConfig, error) {
	httpReadTimeout, err := time.ParseDuration(*c.HTTPReadTimeout)
	if err != nil {
		return nil, fmt.Errorf("error parsing HTTPReadTimeout: %w", err)
	}

	httpMaxSize, err := humanize.ParseBytes(*c.HTTPMaxSize)
	if err != nil {
		return nil, fmt.Errorf("error parsing HTTPMaxSize: %w", err)
	}

	gcsTimeout, err := time.ParseDuration(*c.GCSTimeout)
	if err != nil {
		return nil, fmt.Errorf("error parsing GCSTimeout: %w", err)
	}

	gitTimeout, err := time.ParseDuration(*c.GitTimeout)
	if err != nil {
		return nil, fmt.Errorf("error parsing GitTimeout: %w", err)
	}

	hgTimeout, err := time.ParseDuration(*c.HgTimeout)
	if err != nil {
		return nil, fmt.Errorf("error parsing HgTimeout: %w", err)
	}

	s3Timeout, err := time.ParseDuration(*c.S3Timeout)
	if err != nil {
		return nil, fmt.Errorf("error parsing S3Timeout: %w", err)
	}

	decompressionSizeLimit, err := humanize.ParseBytes(*c.DecompressionSizeLimit)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Append a valid Go duration unit to the value: use "30s", "5m", "1h30m" instead of a bare number
  2. Check the rendered Nomad agent config for the gcs_timeout value and ensure it is non-empty and unit-suffixed
  3. Pre-validate with time.ParseDuration in the code that assembles the config to fail earlier with context

Example fix

// before
gcs_timeout = "120"
// after
gcs_timeout = "120s"
Defensive patterns

Strategy: validation

Validate before calling

if _, err := time.ParseDuration(*c.GCSTimeout); err != nil {
    return fmt.Errorf("invalid gcs_timeout %q: %w", *c.GCSTimeout, err)
}

Type guard

func validDuration(s *string) bool { if s == nil { return false }; _, err := time.ParseDuration(*s); return err == nil }

Try / catch

cfg, err := config.ArtifactConfigFromAgent(agentCfg)
if err != nil {
    if strings.Contains(err.Error(), "error parsing GCSTimeout") {
        return fmt.Errorf("gcs_timeout must be a Go duration like 30s: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ArtifactConfigFromAgent when the agent ArtifactConfig's GCSTimeout points to a string like "30", "30sec", "thirty seconds", "" or "1h30m" misspellings that time.ParseDuration rejects.

Common situations: gcs_timeout set in the Nomad client artifact config block without a time unit (e.g. "30" instead of "30s"); values sourced from environment variables or templates that render empty; hand-written configs in tests.

Understand the failure class

Related errors


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