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.EnforcementView on GitHub (pinned to 482b49bf1a)
Solutions
- Set server.start_timeout to a positive duration, e.g. start_timeout = "30s".
- Remove the start_timeout key entirely to fall back to the default value.
- 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
- Always include a unit suffix and a positive value for start_timeout.
- Add a config-lint step validating durations with time.ParseDuration and d > 0.
- Prefer omitting the key over setting 0 to 'disable' it.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- error parsing rpc_handshake_timeout: %v
- Error parsing max kill timeout: %s
- start_block_for %v not a valid duration: %v
- plugin_exit_after %v not a valid duration: %v
- http_read_timeout not a valid duration: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/df21fe59c7958823.
Report an issue: GitHub.