netbirdio/netbird · error

profile '%s' does not exist

Error message

profile '%s' does not exist

What it means

The id passed validation but os.Stat found no config file at the built path: for "default" that is configDir/netbird.cfg, otherwise configDir/profiles/<id>.json. The profile was never created, was already removed, or lives under a different configDir.

Source

Thrown at client/android/profile_manager.go:186

	log.Infof("created new profile: %s", profile.ID)
	return nil
}

// LogoutProfile logs out from a profile (clears authentication)
func (pm *ProfileManager) LogoutProfile(id string) error {
	configPath, err := pm.getProfileConfigPath(id)
	if err != nil {
		return err
	}

	if !profilemanager.IsValidProfileFilenameStem(profilemanager.ID(id)) {
		return fmt.Errorf("id '%s' is not valid", id)
	}

	// Check if profile exists
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		return fmt.Errorf("profile '%s' does not exist", id)
	}

	// Read current config using internal profilemanager
	config, err := profilemanager.ReadConfig(configPath)
	if err != nil {
		return fmt.Errorf("failed to read profile config: %w", err)
	}

	// Clear authentication by removing private key and SSH key
	config.PrivateKey = ""
	config.SSHKey = ""

	// Save config using internal profilemanager
	if err := profilemanager.WriteOutConfig(configPath, config); err != nil {
		return fmt.Errorf("failed to save config: %w", err)
	}

	// The stored account email is kept on purpose, matching the desktop and CLI

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Refresh the profile list before offering logout, and act only on current ids
  2. On fresh installs, complete a login first so the config file exists
  3. Treat 'does not exist' as already-logged-out if the UX allows

Example fix

// before: logout straight from a cached list entry
pm.LogoutProfile(cachedId)

// after: act only on ids that still exist
list, err := pm.ListProfiles() // refresh
if err == nil {
	for i := 0; i < list.Length(); i++ {
		if list.Get(i).ID == cachedId {
			_ = pm.LogoutProfile(cachedId)
		}
	}
}
Defensive patterns

Strategy: validation

Validate before calling

// Only offer logout for profiles that still exist
list, err := pm.ListProfiles()
if err == nil && !containsId(list, id) {
	// profile already gone; skip the logout call
}

Try / catch

if err := pm.LogoutProfile(id); err != nil {
	if strings.Contains(err.Error(), "does not exist") {
		// treat as logged out; refresh UI list
	} else {
		// real I/O or parse failure: inspect the file
	}
}

Prevention

When it happens

Trigger: LogoutProfile on the default profile before any login created netbird.cfg (fresh install), logging out a profile that RemoveProfile already deleted, or a stale UI list acting on ids whose files are gone.

Common situations: First-run logout attempt, double logout, app data cleared while the UI cached the profile list, configDir mismatch after a migration.

Related errors


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