hashicorp/nomad · error
https_handshake_timeout must be >= 0
Error message
https_handshake_timeout must be >= 0
What it means
Returned by NewHTTPServers (command/agent/http.go:135) when `limits.https_handshake_timeout` parses as a duration but is negative. A negative TLS handshake timeout is nonsensical, so the agent refuses to start the HTTP servers.
Source
Thrown at command/agent/http.go:135
wsUpgrader *websocket.Upgrader
}
// NewHTTPServers starts an HTTP server for every address.http configured in
// the agent.
func NewHTTPServers(agent *Agent, config *Config) ([]*HTTPServer, error) {
var (
srvs []*HTTPServer
serverInitializationErrors error
connCount atomic.Int32
)
// Get connection handshake timeout limit
handshakeTimeout, err := time.ParseDuration(config.Limits.HTTPSHandshakeTimeout)
if err != nil {
return srvs, fmt.Errorf("error parsing https_handshake_timeout: %v", err)
} else if handshakeTimeout < 0 {
return srvs, fmt.Errorf("https_handshake_timeout must be >= 0")
}
// Get max connection limit
maxConns := 0
if mc := config.Limits.HTTPMaxConnsPerClient; mc != nil {
maxConns = *mc
}
if maxConns < 0 {
return srvs, fmt.Errorf("http_max_conns_per_client must be >= 0")
}
tlsConf, err := tlsutil.NewTLSConfiguration(config.TLSConfig, config.TLSConfig.VerifyHTTPSClient, true)
if err != nil && config.TLSConfig.EnableHTTP {
return srvs, fmt.Errorf("failed to initialize HTTP server TLS configuration: %s", err)
}
wsUpgrader := &websocket.Upgrader{
ReadBufferSize: 2048,View on GitHub (pinned to 482b49bf1a)
Solutions
- Set a non-negative duration, e.g. https_handshake_timeout = "5s".
- Remove the setting entirely to use defaults if the value was a negative sentinel.
- Run `nomad validate` on the config before starting the agent.
- If reload triggered it, correct the config and reload again.
Example fix
// before (HCL)
limits {
https_handshake_timeout = "-1s"
}
// after
limits {
https_handshake_timeout = "5s"
} Defensive patterns
Strategy: validation
Validate before calling
d, err := time.ParseDuration(cfg.Limits.HTTPSHandshakeTimeout)
if err != nil || d < 0 {
return fmt.Errorf("https_handshake_timeout must be a non-negative duration")
} Type guard
func validHandshakeTimeout(v string) bool {
d, err := time.ParseDuration(v)
return err == nil && d >= 0
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "https_handshake_timeout must be >= 0") {
// replace negative sentinel with default by removing the setting
}
} Prevention
- Never use negative numbers as 'unset' sentinels in config.
- Validate signs in templated config generation.
- Run `nomad validate` before starting agents.
When it happens
Trigger: Setting `limits { https_handshake_timeout = "-1s" }` or any negative duration, then starting or reloading the agent's HTTP server.
Common situations: Sign typos; templating interpolating a negative sentinel meaning 'unset'; operators attempting to disable the timeout with a negative number instead of removing the setting.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 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
- Reschedule policy has unlimited attempts enabled and a low d
- Lock delay and TTL must be positive
- cannot reload agent with nil configuration
- http_max_conns_per_client must be >= 0
- failed to initialize HTTP server TLS configuration: %s
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/31caf98f4015f7d8.
Report an issue: GitHub.