hashicorp/nomad · error

start_timeout should be greater than 0s

Error message

start_timeout should be greater than 0s

What it means

Nomad's convertServerConfig parses the server { start_timeout = "..." } agent config value with time.ParseDuration and rejects any parsed duration that is zero or negative. StartTimeout bounds how long a server waits for peers during startup, so a non-positive value is meaningless and would break startup logic. The error aborts agent configuration before the server is created.

Source

Thrown at command/agent/agent.go:721

	}
	jobMaxSourceBytes, err := humanize.ParseBytes(*agentConfig.Server.JobMaxSourceSize)
	if err != nil {
		return nil, fmt.Errorf("failed to parse max job source bytes: %w", err)
	}
	conf.JobMaxSourceSize = int(jobMaxSourceBytes)

	conf.Reporting = agentConfig.Reporting
	// Pass the server's production status through to the reporting config
	conf.Reporting.NonProduction = agentConfig.Server.NonProduction

	conf.KEKProviderConfigs = agentConfig.KEKProviders

	if startTimeout := agentConfig.Server.StartTimeout; startTimeout != "" {
		dur, err := time.ParseDuration(startTimeout)
		if err != nil {
			return nil, fmt.Errorf("failed to parse start_timeout: %v", err)
		} else if dur <= time.Duration(0) {
			return nil, fmt.Errorf("start_timeout should be greater than 0s")
		}
		conf.StartTimeout = dur
	}

	// Ensure the passed number of scheduler is between the bounds of zero and
	// the number of CPU cores on the machine. The runtime CPU count object is
	// populated at process start time, so there is no overhead in calling the
	// function compared to saving the value.
	if conf.NumSchedulers < 0 || conf.NumSchedulers > runtime.NumCPU() {
		return nil, fmt.Errorf("number of schedulers should be between 0 and %d",
			runtime.NumCPU())
	}

	// If the operator has specified a client introduction server config block,
	// translate this into the internal server configuration object.
	if agentConfig.Server.ClientIntroduction != nil {
		if agentConfig.Server.ClientIntroduction.Enforcement != "" {
			conf.NodeIntroductionConfig.Enforcement = agentConfig.Server.ClientIntroduction.Enforcement

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set server.start_timeout to a positive duration, e.g. start_timeout = "30s".
  2. Remove the start_timeout key entirely to fall back to the default value.
  3. Verify the duration string parses with Go time.ParseDuration semantics (e.g. "5s", "1m30s").

Example fix

// before
server {
  start_timeout = "0s"
}
// after
server {
  start_timeout = "30s"
}
Defensive patterns

Strategy: validation

Validate before calling

if v, ok := cfg.Get("server.start_timeout"); ok {
  d, err := time.ParseDuration(v)
  if err != nil || d <= 0 {
    return fmt.Errorf("start_timeout must be a positive duration, got %q", v)
  }
}

Prevention

When it happens

Trigger: Setting server.start_timeout to "0", "0s", a negative value like "-5s", or any value that parses to dur <= 0 in the Nomad agent config, then starting the agent or triggering a reload (handleReload) that re-runs convertServerConfig.

Common situations: Copy-pasted config snippets with start_timeout = "0s" to 'disable' the timeout; templating tools substituting an empty/zero default; typos intending a large timeout; automated config generators producing negative durations from calculations.

Understand the failure class

Related errors


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