netbirdio/netbird · error

no available port found from configured redirect URLs: %q

Error message

no available port found from configured redirect URLs: %q

What it means

Returned by NewPKCEAuthorizationFlow when every configured redirect URL is unusable (client/internal/auth/pkce_flow.go:109-111). A URL is skipped when isRedirectURLPortUsed reports its port occupied (a successful TCP dial to host:port) or inside OS-excluded port ranges (pkce_flow.go:364-396; on Windows, reserved ranges from getSystemExcludedPortRanges). If none of RedirectURLs survives, no local callback server can start and flow construction fails.

Source

Thrown at client/internal/auth/pkce_flow.go:110

	codeVerifier   string
	oAuthConfig    *oauth2.Config
}

// NewPKCEAuthorizationFlow returns new PKCE authorization code flow.
func NewPKCEAuthorizationFlow(config PKCEAuthProviderConfig) (*PKCEAuthorizationFlow, error) {
	var availableRedirectURL string

	excludedRanges := getSystemExcludedPortRanges()

	for _, redirectURL := range config.RedirectURLs {
		if !isRedirectURLPortUsed(redirectURL, excludedRanges) {
			availableRedirectURL = redirectURL
			break
		}
	}

	if availableRedirectURL == "" {
		return nil, fmt.Errorf("no available port found from configured redirect URLs: %q", config.RedirectURLs)
	}

	cfg := &oauth2.Config{
		ClientID:     config.ClientID,
		ClientSecret: config.ClientSecret,
		Endpoint: oauth2.Endpoint{
			AuthURL:  config.AuthorizationEndpoint,
			TokenURL: config.TokenEndpoint,
		},
		RedirectURL: availableRedirectURL,
		Scopes:      strings.Split(config.Scope, " "),
	}

	return &PKCEAuthorizationFlow{
		providerConfig: config,
		oAuthConfig:    cfg,
	}, nil
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Free the occupied port: finish or kill the other login attempt / process listening on the redirect port (netstat -ano | grep <port>)
  2. On Windows, inspect reserved ranges: netsh int ipv4 show excludedportrange protocol=tcp - if they cover your ports, restart winnat (net stop winnat && net start winnat) or have the admin add redirect URLs on unreserved ports
  3. Administrator: configure multiple redirect URLs on widely separated ports in the IdP/management config so at least one is free
  4. Retry netbird up once ports are released
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check candidate redirect ports before constructing the flow
func portAvailable(rawURL string) bool {
	u, err := url.Parse(rawURL)
	if err != nil {
		return false
	}
	ln, err := net.Listen("tcp", net.JoinHostPort("127.0.0.1", u.Port()))
	if err != nil {
		return false
	}
	return ln.Close() == nil
}

// usable := 0
// for _, r := range redirectURLs { if portAvailable(r) { usable++ } }

Try / catch

flow, err := auth.NewPKCEAuthorizationFlow(cfg)
if err != nil && strings.Contains(err.Error(), "no available port found from configured redirect URLs") {
	// free the listed ports or extend the redirect URL list in the IdP/management config
}

Prevention

When it happens

Trigger: For each redirect URL, either another process already listens on its port (another netbird login in progress, any app on that port) or the port falls in a Windows excluded range (Hyper-V/WinNAT dynamic reservations). All configured ports failing simultaneously produces this error.

Common situations: Windows machines where Hyper-V/WSD reserves wide port ranges that overlap NetBird's configured loopback ports; a previous netbird up still holding the callback port; concurrent logins from the desktop app and CLI; Docker/WSL workloads binding the same localhost ports.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/b5d9fd85f30a917f. Report an issue: GitHub.