fatedier/frp · error

failed to parse OIDC proxy URL %q: %w

Error message

failed to parse OIDC proxy URL %q: %w

What it means

frpc's OIDC authentication builds a dedicated HTTP client for the token endpoint. When oidc.proxyURL is set, that string is passed to Go's url.Parse; if parsing fails the client construction aborts with this wrapped error. url.Parse only rejects structurally invalid URLs (e.g. control characters, missing scheme like 'host:8080' being misread), so in practice the configured value is malformed rather than merely unreachable.

Source

Thrown at pkg/auth/oidc.go:68

			if err != nil {
				return nil, fmt.Errorf("failed to read OIDC CA certificate file %q: %w", trustedCAFile, err)
			}

			caCertPool := x509.NewCertPool()
			if !caCertPool.AppendCertsFromPEM(caCert) {
				return nil, fmt.Errorf("failed to parse OIDC CA certificate from file %q", trustedCAFile)
			}

			tlsConfig.RootCAs = caCertPool
		}
		transport.TLSClientConfig = tlsConfig
	}

	// Configure proxy settings
	if proxyURL != "" {
		parsedURL, err := url.Parse(proxyURL)
		if err != nil {
			return nil, fmt.Errorf("failed to parse OIDC proxy URL %q: %w", proxyURL, err)
		}
		transport.Proxy = http.ProxyURL(parsedURL)
	} else {
		// Explicitly disable proxy to override DefaultTransport's ProxyFromEnvironment
		transport.Proxy = nil
	}

	return &http.Client{Transport: transport}, nil
}

// nonCachingTokenSource wraps a clientcredentials.Config to fetch a fresh
// token on every call. This is used as a fallback when the OIDC provider
// does not return expires_in, which would cause a caching TokenSource to
// hold onto a stale token forever.
type nonCachingTokenSource struct {
	cfg *clientcredentials.Config
	ctx context.Context
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Correct the proxy URL to a fully qualified form with scheme and host, e.g. http://proxy.example.com:8080 or socks5://127.0.0.1:1080
  2. Verify scheme spelled exactly http, https, or socks5 followed by '://'
  3. Remove any surrounding quotes, spaces, or stray characters from the config value
  4. Test the value in isolation: url.Parse("socks5://127.0.0.1:1080") must succeed

Example fix

// frpc.toml before
authentication.method = "oidc"
authentication.oidc.proxyURL = "127.0.0.1:8080"

// after
authentication.method = "oidc"
authentication.oidc.proxyURL = "http://127.0.0.1:8080"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(proxyURL)
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("oidc.proxyURL must be a full URL like http://host:port, got %q", proxyURL)
}

Try / catch

if err := validateProxyURL(cfg.ProxyURL); err != nil { return err } // fail fast before NewOidcAuthProvider

Prevention

When it happens

Trigger: Client config with authentication.oidc enabled and oidc.proxyURL set to a value Go cannot parse: 'socks5 :1080' (space instead of ://), '127.0.0.1:8080' (parsed as scheme '127.0.0.1'), a URL containing spaces or control characters, or a scheme with invalid characters.

Common situations: Routing frpc's OIDC token fetch through a corporate proxy; users write a bare host:port without the http:// scheme, or copy a proxy address with a typo; recently migrating from env-var HTTP_PROXY to the explicit oidc.proxyURL field.

Understand the failure class

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/a2bb99381940fd66. Report an issue: GitHub.