netbirdio/netbird · error
failed to parse redirect URL: %v
Error message
failed to parse redirect URL: %v
What it means
Returned by PKCEAuthorizationFlow.WaitToken when url.Parse rejects the selected redirect URL (client/internal/auth/pkce_flow.go:196-199). The parsed URL's port is needed to bind the local callback server (http.Server on ':'+port). url.Parse fails only on truly malformed input - ASCII control characters or invalid percent-encoding - so in practice this means the redirect URL stored in the management/IdP configuration is malformed. Note the URL already passed isRedirectURLPortUsed during flow construction, which also parses and would have logged a parse failure there.
Source
Thrown at client/internal/auth/pkce_flow.go:198
// WaitToken waits for the OAuth token in the PKCE Authorization Flow.
// It starts an HTTP server to receive the OAuth token callback and waits for the token or an error.
// Once the token is received, it is converted to TokenInfo and validated before returning.
// The method creates a timeout context internally based on info.ExpiresIn.
func (p *PKCEAuthorizationFlow) WaitToken(ctx context.Context, info AuthFlowInfo) (TokenInfo, error) {
// Create timeout context based on flow expiration
timeout := time.Duration(info.ExpiresIn) * time.Second
waitCtx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
log.Infof("pkce flow: waiting for authorization callback on %s, timeout %s", p.oAuthConfig.RedirectURL, timeout)
tokenChan := make(chan *oauth2.Token, 1)
errChan := make(chan error, 1)
parsedURL, err := url.Parse(p.oAuthConfig.RedirectURL)
if err != nil {
return TokenInfo{}, fmt.Errorf("failed to parse redirect URL: %v", err)
}
server := &http.Server{Addr: fmt.Sprintf(":%s", parsedURL.Port())}
defer func() {
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(shutdownCtx); err != nil {
log.Errorf("failed to close the server: %v", err)
}
}()
go p.startServer(server, tokenChan, errChan)
select {
case <-waitCtx.Done():
return TokenInfo{}, waitCtx.Err()
case token := <-tokenChan:View on GitHub (pinned to 93e97f4bf1)
Solutions
- Administrator: re-enter the redirect URL in the management/IdP configuration cleanly (e.g. http://localhost:53000/callback), avoiding pasted control characters
- Verify with a quick parse before deploying config changes (see validationCode)
- End user: retry after the corrected config is fetched from management
Example fix
// before: config with a stray control character
RedirectURLs: []string{"http://localhost:53000/callback\n"}
// after: clean URL
RedirectURLs: []string{"http://localhost:53000/callback"} Defensive patterns
Strategy: validation
Validate before calling
// Administrator-side: validate redirect URLs before saving them into the IdP integration
func validRedirectURL(raw string) error {
u, err := url.Parse(raw)
if err != nil {
return fmt.Errorf("redirect URL %q is not parseable: %w", raw, err)
}
if u.Port() == "" {
return fmt.Errorf("redirect URL %q must include an explicit port", raw)
}
return nil
} Try / catch
if err != nil && strings.Contains(err.Error(), "failed to parse redirect URL") {
// malformed URL in management/IdP config: strip control characters (e.g. trailing newline) and re-save
} Prevention
- Type redirect URLs manually or sanitize pasted values (no trailing newlines, spaces, or control characters)
- Validate URLs in config automation with url.Parse before publishing
- Remember url.Parse only rejects control characters and bad percent-escapes - most typos parse fine but break the flow later
When it happens
Trigger: p.oAuthConfig.RedirectURL contains control characters (e.g. a stray newline or NUL pasted into the admin config) or an invalid escape like '%zz'. url.Parse errors where a hostname would not: most typo'd URLs (missing scheme, bad port text) still parse, only control chars and broken percent-escapes do not.
Common situations: Copy-paste artifacts in the IdP integration config on management (trailing newline, hidden whitespace/control char), or programmatic config writes that injected unescaped characters.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- listen_port is not supported for HTTP services
- domain is required for TCP/UDP services (used for cluster de
- auth is not supported for TCP/UDP services
- TCP/UDP services must have exactly one target
- listen_port is required for TLS services
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/0cce12b3f7b073a7.
Report an issue: GitHub.