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
- Run 'netbird profile list' and pass the exact name or the full ID
- When names collide, include the correct --username so the daemon can disambiguate
- If the ID prefix is ambiguous, use the complete ID
- 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
- Always quote profile names in scripts to prevent shell splitting
- Prefer full IDs over prefixes in automation
- Keep usernames aligned with profile ownership when multiple humans share a workstation
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
- switch profile: %v
- switch profile on daemon: %v
- wait for extend session: %v
- active profile not found, please run 'netbird profile create
- get active profile file path: %v
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/d46636cb12e6474a.
Report an issue: GitHub.