hashicorp/nomad · error
error parsing rpc_handshake_timeout: %v
Error message
error parsing rpc_handshake_timeout: %v
What it means
The limits.rpc_handshake_timeout value is parsed with time.ParseDuration, which requires a Go duration string like "5s" or "500ms". If the value is absent-but-nonempty garbage or malformed (e.g. "5" with no unit, "five seconds"), ParseDuration fails and convertServerConfig returns this wrapped error, aborting agent startup or config reload.
Source
Thrown at command/agent/agent.go:596
if agentConfig.RPC.StreamOpenTimeout > 0 {
conf.RPCSessionConfig.StreamOpenTimeout = agentConfig.RPC.StreamOpenTimeout
}
if agentConfig.RPC.DialTimeout > 0 {
conf.RPCDialTimeout = agentConfig.RPC.DialTimeout
}
}
// Set the TLS config
conf.TLSConfig = agentConfig.TLSConfig
// Setup telemetry related config
conf.StatsCollectionInterval = agentConfig.Telemetry.collectionInterval
conf.DisableDispatchedJobSummaryMetrics = agentConfig.Telemetry.DisableDispatchedJobSummaryMetrics
conf.DisableQuotaUtilizationMetrics = agentConfig.Telemetry.DisableQuotaUtilizationMetrics
conf.DisableRPCRateMetricsLabels = agentConfig.Telemetry.DisableRPCRateMetricsLabels
if d, err := time.ParseDuration(agentConfig.Limits.RPCHandshakeTimeout); err != nil {
return nil, fmt.Errorf("error parsing rpc_handshake_timeout: %v", err)
} else if d < 0 {
return nil, fmt.Errorf("rpc_handshake_timeout must be >= 0")
} else {
conf.RPCHandshakeTimeout = d
}
// Set max rpc conns; nil/0 == unlimited
// Leave a little room for streaming RPCs
minLimit := config.LimitsNonStreamingConnsPerClient + 5
if agentConfig.Limits.RPCMaxConnsPerClient == nil || *agentConfig.Limits.RPCMaxConnsPerClient == 0 {
conf.RPCMaxConnsPerClient = 0
} else if limit := *agentConfig.Limits.RPCMaxConnsPerClient; limit <= minLimit {
return nil, fmt.Errorf("rpc_max_conns_per_client must be > %d; found: %d", minLimit, limit)
} else {
conf.RPCMaxConnsPerClient = limit
}
// Set deployment rate limitView on GitHub (pinned to 482b49bf1a)
Solutions
- Change the value to a valid Go duration string with a unit, e.g. rpc_handshake_timeout = "5s"
- Remove the rpc_handshake_timeout line entirely to use the default
- Check for stray whitespace, quotes, or locale-formatted numbers in the config value
- Validate with nomad agent config / config validate before deploying if available
Example fix
// before
limits {
rpc_handshake_timeout = "5"
}
// after
limits {
rpc_handshake_timeout = "5s"
} Defensive patterns
Strategy: validation
Validate before calling
// Go: pre-validate duration strings before writing the config
func validDuration(s string) bool {
_, err := time.ParseDuration(s)
return s == "" || err == nil
}
// reject values like "5" early
if !validDuration(cfg.Limits.RPCHandshakeTimeout) { ... } Type guard
func isGoDuration(s string) bool {
_, err := time.ParseDuration(s)
return err == nil
} Try / catch
// wrap agent start to surface config errors clearly
conf, err := convertServerConfig(agentConfig)
if err != nil {
return fmt.Errorf("server config invalid: %w", err)
} Prevention
- Always include a unit (s, ms, m) in duration settings
- Validate config with nomad validate in CI before rollout
- Never paste bare numbers from tools with implicit-seconds semantics
When it happens
Trigger: Setting limits { rpc_handshake_timeout = "5" } (missing unit), or any string that is not a valid Go duration (empty string, "5 sec", negative-looking typos like "-5s" handled separately by 1102) when starting or reloading a Nomad server.
Common situations: Users copying values from Prometheus/other tools that use plain numbers with implicit seconds; YAML/JSON configs where a numeric 5 gets stringified oddly; hand-edits adding the option without knowing Go duration syntax.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- server_service_name must be set when auto_advertise is enabl
- start_timeout should be greater than 0s
- Error parsing max kill timeout: %s
- start_block_for %v not a valid duration: %v
- plugin_exit_after %v not a valid duration: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/e860ebdd26c51510.
Report an issue: GitHub.