netbirdio/netbird · error
switch profile: %v
Error message
switch profile: %v
What it means
Top-level wrapper for the whole profile-switch stage of getActiveProfile: when --profile-name is passed, switchProfileOnDaemon runs a chain (daemon RPC to resolve the profile, local pm.SwitchProfile to persist the active pointer, daemon Status check, optional Down call) and this error reports that one of those steps failed. The inner message ('switch profile on daemon', 'switch profile', 'unable to get daemon status') identifies which link broke.
Source
Thrown at client/cmd/login.go:239
if ts := waitResp.GetSessionExpiresAt(); ts.IsValid() && !ts.AsTime().IsZero() {
deadline := ts.AsTime().Local()
cmd.Printf("Session extended. New expiry: %s\n", deadline.Format("2006-01-02 15:04:05 MST"))
} else {
// Management reported the peer is not eligible (e.g. login
// expiration disabled on the account). Surface that fact
// instead of pretending the call succeeded.
cmd.Println("Session extension call completed, but the management server did not return a new deadline (peer may not be SSO-tracked or login expiration is disabled).")
}
return nil
}
func getActiveProfile(ctx context.Context, pm *profilemanager.ProfileManager, profileName string, username string) (*profilemanager.Profile, error) {
// switch profile if provided
if profileName != "" {
if err := switchProfileOnDaemon(ctx, pm, profileName, username); err != nil {
return nil, fmt.Errorf("switch profile: %v", err)
}
}
activeProf, err := pm.GetActiveProfile()
if err != nil {
return nil, fmt.Errorf("get active profile: %v", err)
}
if activeProf == nil {
return nil, fmt.Errorf("active profile not found, please run 'netbird profile create' first")
}
return activeProf, nil
}
func switchProfileOnDaemon(ctx context.Context, pm *profilemanager.ProfileManager, handle string, username string) error {
resolvedID, err := switchProfile(ctx, handle, username)
if err != nil {
return fmt.Errorf("switch profile on daemon: %v", err)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Run 'netbird profile list' and pass the exact profile name or full ID
- Ensure the daemon is up: 'netbird service install && netbird service start'
- Check write permissions on the CLI config dir (~/.netbird or NB_CONFIG_DIR) if the inner error is the local 'switch profile' step
- Read the inner wrapped message and apply the fix for the failing sub-step (errors 224-227)
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the target profile exists before switching
pm := profilemanager.NewProfileManager()
profiles, err := pm.GetProfiles()
if err == nil {
for _, p := range profiles {
if p.Name == profileName {
return nil // safe to proceed with getActiveProfile
}
}
return fmt.Errorf("profile %q not found; run 'netbird profile list'", profileName)
} Try / catch
prof, err := getActiveProfile(ctx, pm, profileName, username)
if err != nil {
inner := errors.Unwrap(err)
if strings.HasPrefix(inner.Error(), "switch profile on daemon") {
// daemon-side: check service, exact profile name
}
return err
} Prevention
- Pin automation to full profile IDs, not names, to survive renames
- Run 'netbird profile list' in scripts before switching to assert the profile exists
- Keep daemon ownership and config-dir ownership under the same user
When it happens
Trigger: Passing --profile-name that does not exist or is ambiguous; daemon not running when the CLI dials it; local profile store not writable when persisting the active profile; daemon connected and the subsequent Down RPC fails.
Common situations: Typos in profile names after 'netbird profile list' output changed; running the CLI as a different user than the one who owns the config dir; daemon mid-restart during service upgrade; read-only home directory (NFS root-squash, container).
Related errors
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/08c3c0059ddd9b7e.
Report an issue: GitHub.