netbirdio/netbird · error

switch profile failed: %w

Error message

switch profile failed: %w

What it means

The daemon answered the SwitchProfile RPC itself with a gRPC error: no profile matched the supplied ProfileName+Username combination, the unique-ID prefix was ambiguous, or the daemon failed while loading the requested profile. Unlike its siblings, this uses %w, so the gRPC status is unwrappable with errors.As/errors.Is for programmatic handling.

Source

Thrown at client/cmd/login.go:309

// re-resolving the handle.
func switchProfile(ctx context.Context, handle string, username string) (profilemanager.ID, error) {
	conn, err := DialClientGRPCServer(ctx, daemonAddr)
	if err != nil {
		//nolint
		return "", fmt.Errorf("failed to connect to daemon error: %v\n"+
			"If the daemon is not running please run: "+
			"\nnetbird service install \nnetbird service start\n", err)
	}
	defer conn.Close()

	client := proto.NewDaemonServiceClient(conn)

	resp, err := client.SwitchProfile(ctx, &proto.SwitchProfileRequest{
		ProfileName: &handle,
		Username:    &username,
	})
	if err != nil {
		return "", fmt.Errorf("switch profile failed: %w", err)
	}

	return profilemanager.ID(resp.Id), nil
}

func doForegroundLogin(ctx context.Context, cmd *cobra.Command, setupKey string, activeProf *profilemanager.Profile) error {

	err := handleRebrand(cmd)
	if err != nil {
		return err
	}

	// update host's static platform and system information
	system.UpdateStaticInfoAsync()

	configFilePath, err := activeProf.FilePath()
	if err != nil {
		return fmt.Errorf("get active profile file path: %v", err)

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Run 'netbird profile list' and pass the exact name or the full ID
  2. When names collide, include the correct --username so the daemon can disambiguate
  3. If the ID prefix is ambiguous, use the complete ID
  4. For daemon-side load errors, inspect the daemon logs for the profile file it failed to parse

Example fix

# before
$ netbird login --profile-name corp
Error: switch profile failed: rpc error: code = NotFound

# after: list, then use the full name or ID
$ netbird profile list
ID            NAME      USER
cx3f corp-fmt  alice
$ netbird login --profile-name corp-fmt
# or: netbird login --profile-name cx3f9a12...
Defensive patterns

Strategy: validation

Validate before calling

// Exact-match pre-check avoids NotFound and ambiguity before the RPC
profiles, _ := pm.GetProfiles()
matches := 0
for _, p := range profiles {
    if p.Name == handle || strings.HasPrefix(string(p.ID), handle) {
        matches++
    }
}
if matches == 0 {
    return fmt.Errorf("%q matches no profile", handle)
}
if matches > 1 {
    return fmt.Errorf("%q is ambiguous; use the full profile ID", handle)
}

Try / catch

// %w is used, so the gRPC status survives wrapping
if _, err := client.SwitchProfile(ctx, req); err != nil {
    if status.Code(err) == codes.NotFound {
        return fmt.Errorf("profile %q not found for user %q: %w", handle, username, err)
    }
    return fmt.Errorf("switch profile failed: %w", err)
}

Prevention

When it happens

Trigger: Passing a profile name that does not exist (typo, deleted profile); passing a name that belongs to a different username when the username filter is set; a short profile ID that matches multiple profiles; daemon-side load error on a corrupted profile file.

Common situations: Scripts pinning a profile name that was renamed; Multiple users on one host with same-named profiles but --username omitted; Copy-pasted truncated IDs from 'netbird profile list'

Related errors


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