netbirdio/netbird · error

failed to create auth client: %v

Error message

failed to create auth client: %v

What it means

Returned by authenticateWithPKCEFlow when NewAuth fails to build the management gRPC client before fetching PKCE provider info (client/internal/auth/oauth.go:89-92). NewAuth dials config.ManagementURL with the host's private key, so failures are connectivity or identity level: management unreachable, TLS handshake failure, or login/registration rejected. Note: NewOAuthFlow catches this error, logs it at debug level, and falls back to the device code flow, so end users normally see it only as a debug log line preceding a device-flow attempt (or its sibling, error 927).

Source

Thrown at client/internal/auth/oauth.go:91

func NewOAuthFlow(ctx context.Context, config *profilemanager.Config, isUnixDesktopClient bool, forceDeviceCodeFlow bool, hint string) (OAuthFlow, error) {
	if shouldUseDeviceFlow(forceDeviceCodeFlow, isUnixDesktopClient) {
		return authenticateWithDeviceCodeFlow(ctx, config, hint)
	}

	pkceFlow, err := authenticateWithPKCEFlow(ctx, config, hint)
	if err != nil {
		log.Debugf("failed to initialize pkce authentication with error: %v\n", err)
		log.Debug("falling back to device code flow")
		return authenticateWithDeviceCodeFlow(ctx, config, hint)
	}
	return pkceFlow, nil
}

// authenticateWithPKCEFlow initializes the Proof Key for Code Exchange flow auth flow
func authenticateWithPKCEFlow(ctx context.Context, config *profilemanager.Config, hint string) (OAuthFlow, error) {
	authClient, err := NewAuth(ctx, config.PrivateKey, config.ManagementURL, config)
	if err != nil {
		return nil, fmt.Errorf("failed to create auth client: %v", err)
	}
	defer authClient.Close()

	pkceFlowInfo, err := authClient.getPKCEFlow(authClient.client)
	if err != nil {
		return nil, fmt.Errorf("getting pkce authorization flow info failed with error: %v", err)
	}

	if hint != "" {
		pkceFlowInfo.SetLoginHint(hint)
	}

	return pkceFlowInfo, nil
}

// authenticateWithDeviceCodeFlow initializes the Device Code auth Flow
func authenticateWithDeviceCodeFlow(ctx context.Context, config *profilemanager.Config, hint string) (OAuthFlow, error) {
	authClient, err := NewAuth(ctx, config.PrivateKey, config.ManagementURL, config)

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Verify the management URL is reachable: curl -v https://<management-url> from the same machine
  2. Check DNS and firewall rules for the management gRPC port
  3. Inspect the management server logs for the rejected login from this host key
  4. If TLS is the issue, ensure the host trusts the management certificate (system CA store or embedded roots)
Defensive patterns

Strategy: validation

Validate before calling

// Check management reachability before attempting login
func managementReachable(rawURL string) error {
	u, err := url.Parse(rawURL)
	if err != nil {
		return err
	}
	_, err = net.DialTimeout("tcp", u.Host, 5*time.Second)
	if err != nil {
		return fmt.Errorf("management %s not reachable: %w", u.Host, err)
	}
	return nil
}

Try / catch

flow, err := auth.NewOAuthFlow(ctx, cfg, isDesktop, false, hint)
if err != nil {
	// PKCE failures like this fall back to device flow; the surfaced error comes from there.
	// Inspect debug logs to see which stage failed.

Prevention

When it happens

Trigger: NewAuth(ctx, config.PrivateKey, config.ManagementURL, config) fails: management service down or URL wrong, DNS resolution failure, firewall blocking the gRPC port (default 443/33073), TLS certificate mismatch, or the host key not being accepted by management.

Common situations: Self-hosted management behind a load balancer with an expired cert; wrong --management-url after a migration; client clock skew breaking TLS; host not yet registered so the key login fails.

Related errors


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