{"record":{"id":"dc94d420ec8b282a","repo":"nats-io/nats-server","slug":"proxy-timeout-must-be-0","errorCode":null,"errorMessage":"proxy timeout must be >= 0","messagePattern":"proxy timeout must be >= 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/leafnode.go","lineNumber":412,"sourceCode":"\tif remote.Proxy.URL == _EMPTY_ {\n\t\treturn warnings, nil\n\t}\n\n\tproxyURL, err := url.Parse(remote.Proxy.URL)\n\tif err != nil {\n\t\treturn warnings, fmt.Errorf(\"invalid proxy URL: %v\", err)\n\t}\n\n\tif proxyURL.Scheme != \"http\" && proxyURL.Scheme != \"https\" {\n\t\treturn warnings, fmt.Errorf(\"proxy URL scheme must be http or https, got: %s\", proxyURL.Scheme)\n\t}\n\n\tif proxyURL.Host == _EMPTY_ {\n\t\treturn warnings, fmt.Errorf(\"proxy URL must specify a host\")\n\t}\n\n\tif remote.Proxy.Timeout < 0 {\n\t\treturn warnings, fmt.Errorf(\"proxy timeout must be >= 0\")\n\t}\n\n\tif (remote.Proxy.Username == _EMPTY_) != (remote.Proxy.Password == _EMPTY_) {\n\t\treturn warnings, fmt.Errorf(\"proxy username and password must both be specified or both be empty\")\n\t}\n\n\tif len(remote.URLs) > 0 {\n\t\thasWebSocketURL := false\n\t\thasNonWebSocketURL := false\n\n\t\tfor _, remoteURL := range remote.URLs {\n\t\t\tif remoteURL.Scheme == wsSchemePrefix || remoteURL.Scheme == wsSchemePrefixTLS {\n\t\t\t\thasWebSocketURL = true\n\t\t\t\tif (remoteURL.Scheme == wsSchemePrefixTLS) &&\n\t\t\t\t\tremote.TLSConfig == nil && !remote.TLS {\n\t\t\t\t\treturn warnings, fmt.Errorf(\"proxy is configured but remote URL %s requires TLS and no TLS configuration is provided. When using proxy with TLS endpoints, ensure TLS is properly configured for the leafnode remote\", remoteURL.String())\n\t\t\t\t}\n\t\t\t} else {","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/leafnode.go#L394-L430","documentation":"The leafnode remote proxy timeout is negative. validateLeafNodeProxyOptions enforces remote.Proxy.Timeout >= 0 because a negative dial/handshake timeout is meaningless and would be rejected or misbehave downstream in natsDialTimeout. This is a config-time validation error.","triggerScenarios":"Configuring proxy { timeout: -1 } (or any negative value) under a leafnode remote; parsing a duration that resolves negative, e.g. timeout: \"-5s\" or a computed negative time.Duration passed programmatically to parseRemoteLeafNodes.","commonSituations":"Sign typo in config (-5s instead of 5s); arithmetic on durations producing negatives; templates substituting negative defaults.","solutions":["Set the proxy timeout to a non-negative duration, e.g. timeout: \"5s\" or omit it to use the default","Audit config for leading minus signs on duration fields","Clamp computed durations with a max(0, d) before assigning remote.Proxy.Timeout"],"exampleFix":"// before\nproxy {\n  url: \"http://proxy:3128\"\n  timeout: -5s\n}\n// after\nproxy {\n  url: \"http://proxy:3128\"\n  timeout: 5s\n}","handlingStrategy":"validation","validationCode":"if cfg.Proxy != nil && cfg.Proxy.Timeout < 0 {\n    return fmt.Errorf(\"proxy timeout must be >= 0, got %v\", cfg.Proxy.Timeout)\n}","typeGuard":"func validProxyTimeout(d time.Duration) bool { return d >= 0 }","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil { log.Fatalf(\"leafnode config rejected: %v\", r) }\n}()\n// or: check the error from option parsing before starting the server","preventionTips":["Never write negative durations in config files","Clamp computed durations: if d < 0 { d = 0 }","Code-review duration fields for sign errors"],"tags":["configuration","leafnode","proxy","timeout"],"backgroundTag":"invalid-config-value","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}