{"record":{"id":"31caf98f4015f7d8","repo":"hashicorp/nomad","slug":"https-handshake-timeout-must-be-0","errorCode":null,"errorMessage":"https_handshake_timeout must be >= 0","messagePattern":"https_handshake_timeout must be >= 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/http.go","lineNumber":135,"sourceCode":"\n\twsUpgrader *websocket.Upgrader\n}\n\n// NewHTTPServers starts an HTTP server for every address.http configured in\n// the agent.\nfunc NewHTTPServers(agent *Agent, config *Config) ([]*HTTPServer, error) {\n\tvar (\n\t\tsrvs                       []*HTTPServer\n\t\tserverInitializationErrors error\n\t\tconnCount                  atomic.Int32\n\t)\n\n\t// Get connection handshake timeout limit\n\thandshakeTimeout, err := time.ParseDuration(config.Limits.HTTPSHandshakeTimeout)\n\tif err != nil {\n\t\treturn srvs, fmt.Errorf(\"error parsing https_handshake_timeout: %v\", err)\n\t} else if handshakeTimeout < 0 {\n\t\treturn srvs, fmt.Errorf(\"https_handshake_timeout must be >= 0\")\n\t}\n\n\t// Get max connection limit\n\tmaxConns := 0\n\tif mc := config.Limits.HTTPMaxConnsPerClient; mc != nil {\n\t\tmaxConns = *mc\n\t}\n\tif maxConns < 0 {\n\t\treturn srvs, fmt.Errorf(\"http_max_conns_per_client must be >= 0\")\n\t}\n\n\ttlsConf, err := tlsutil.NewTLSConfiguration(config.TLSConfig, config.TLSConfig.VerifyHTTPSClient, true)\n\tif err != nil && config.TLSConfig.EnableHTTP {\n\t\treturn srvs, fmt.Errorf(\"failed to initialize HTTP server TLS configuration: %s\", err)\n\t}\n\n\twsUpgrader := &websocket.Upgrader{\n\t\tReadBufferSize:  2048,","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/http.go#L117-L153","documentation":"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.","triggerScenarios":"Setting `limits { https_handshake_timeout = \"-1s\" }` or any negative duration, then starting or reloading the agent's HTTP server.","commonSituations":"Sign typos; templating interpolating a negative sentinel meaning 'unset'; operators attempting to disable the timeout with a negative number instead of removing the setting.","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."],"exampleFix":"// before (HCL)\nlimits {\n  https_handshake_timeout = \"-1s\"\n}\n// after\nlimits {\n  https_handshake_timeout = \"5s\"\n}","handlingStrategy":"validation","validationCode":"d, err := time.ParseDuration(cfg.Limits.HTTPSHandshakeTimeout)\nif err != nil || d < 0 {\n    return fmt.Errorf(\"https_handshake_timeout must be a non-negative duration\")\n}","typeGuard":"func validHandshakeTimeout(v string) bool {\n    d, err := time.ParseDuration(v)\n    return err == nil && d >= 0\n}","tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"https_handshake_timeout must be >= 0\") {\n        // replace negative sentinel with default by removing the setting\n    }\n}","preventionTips":["Never use negative numbers as 'unset' sentinels in config.","Validate signs in templated config generation.","Run `nomad validate` before starting agents."],"tags":["configuration","validation","tls","nomad"],"backgroundTag":"invalid-config-value","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}