nats-io/nats-server · error

proxy username and password must both be specified or both b

Error message

proxy username and password must both be specified or both be empty

What it means

Proxy credentials are half-specified: exactly one of username or password is empty. The validation requires both to be set or both empty, because a proxy auth header with only one credential is never valid and almost always indicates a config mistake.

Source

Thrown at server/leafnode.go:416

	proxyURL, err := url.Parse(remote.Proxy.URL)
	if err != nil {
		return warnings, fmt.Errorf("invalid proxy URL: %v", err)
	}

	if proxyURL.Scheme != "http" && proxyURL.Scheme != "https" {
		return warnings, fmt.Errorf("proxy URL scheme must be http or https, got: %s", proxyURL.Scheme)
	}

	if proxyURL.Host == _EMPTY_ {
		return warnings, fmt.Errorf("proxy URL must specify a host")
	}

	if remote.Proxy.Timeout < 0 {
		return warnings, fmt.Errorf("proxy timeout must be >= 0")
	}

	if (remote.Proxy.Username == _EMPTY_) != (remote.Proxy.Password == _EMPTY_) {
		return warnings, fmt.Errorf("proxy username and password must both be specified or both be empty")
	}

	if len(remote.URLs) > 0 {
		hasWebSocketURL := false
		hasNonWebSocketURL := false

		for _, remoteURL := range remote.URLs {
			if remoteURL.Scheme == wsSchemePrefix || remoteURL.Scheme == wsSchemePrefixTLS {
				hasWebSocketURL = true
				if (remoteURL.Scheme == wsSchemePrefixTLS) &&
					remote.TLSConfig == nil && !remote.TLS {
					return 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())
				}
			} else {
				hasNonWebSocketURL = true
			}
		}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Provide both proxy username and password in the remote config
  2. If the proxy needs no auth, remove both fields
  3. Verify the secret/env source actually supplies both values at server start

Example fix

// before
proxy {
  url: "http://proxy:3128"
  username: "user"
}
// after
proxy {
  url: "http://proxy:3128"
  username: "user"
  password: "pass"
}
Defensive patterns

Strategy: validation

Validate before calling

p := cfg.Proxy
if p != nil && (p.Username == "") != (p.Password == "") {
    return fmt.Errorf("proxy username and password must both be set or both empty")
}

Type guard

func proxyCredsComplete(p *ProxyOptions) bool {
    return p == nil || (p.Username == "") == (p.Password == "")
}

Try / catch

if err := parseRemoteLeafNodes(cfg); err != nil {
    log.Fatalf("leafnode remote rejected: %v", err)
}

Prevention

When it happens

Trigger: remote.Proxy with Username set but Password empty (or vice versa) in a leafnodes remote config, e.g. proxy { username: "user" } with no password field, or programmatic RemoteLeafOption Proxy with only one credential populated.

Common situations: Password left in an env var that failed to load (empty at runtime); someone redacting/removing the password from config for security and leaving the username; partial secret mounting in Kubernetes where one key is missing.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/058c6a0d599c0082. Report an issue: GitHub.