{"record":{"id":"fd179d0c341f93bc","repo":"netbirdio/netbird","slug":"profile-s-does-not-exist","errorCode":null,"errorMessage":"profile '%s' does not exist","messagePattern":"profile '(.+?)' does not exist","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/android/profile_manager.go","lineNumber":186,"sourceCode":"\n\tlog.Infof(\"created new profile: %s\", profile.ID)\n\treturn nil\n}\n\n// LogoutProfile logs out from a profile (clears authentication)\nfunc (pm *ProfileManager) LogoutProfile(id string) error {\n\tconfigPath, err := pm.getProfileConfigPath(id)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !profilemanager.IsValidProfileFilenameStem(profilemanager.ID(id)) {\n\t\treturn fmt.Errorf(\"id '%s' is not valid\", id)\n\t}\n\n\t// Check if profile exists\n\tif _, err := os.Stat(configPath); os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"profile '%s' does not exist\", id)\n\t}\n\n\t// Read current config using internal profilemanager\n\tconfig, err := profilemanager.ReadConfig(configPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read profile config: %w\", err)\n\t}\n\n\t// Clear authentication by removing private key and SSH key\n\tconfig.PrivateKey = \"\"\n\tconfig.SSHKey = \"\"\n\n\t// Save config using internal profilemanager\n\tif err := profilemanager.WriteOutConfig(configPath, config); err != nil {\n\t\treturn fmt.Errorf(\"failed to save config: %w\", err)\n\t}\n\n\t// The stored account email is kept on purpose, matching the desktop and CLI","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/android/profile_manager.go#L168-L204","documentation":"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.","triggerScenarios":"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.","commonSituations":"First-run logout attempt, double logout, app data cleared while the UI cached the profile list, configDir mismatch after a migration.","solutions":["Refresh the profile list before offering logout, and act only on current ids","On fresh installs, complete a login first so the config file exists","Treat 'does not exist' as already-logged-out if the UX allows"],"exampleFix":"// before: logout straight from a cached list entry\npm.LogoutProfile(cachedId)\n\n// after: act only on ids that still exist\nlist, err := pm.ListProfiles() // refresh\nif err == nil {\n\tfor i := 0; i < list.Length(); i++ {\n\t\tif list.Get(i).ID == cachedId {\n\t\t\t_ = pm.LogoutProfile(cachedId)\n\t\t}\n\t}\n}","handlingStrategy":"validation","validationCode":"// Only offer logout for profiles that still exist\nlist, err := pm.ListProfiles()\nif err == nil && !containsId(list, id) {\n\t// profile already gone; skip the logout call\n}","typeGuard":null,"tryCatchPattern":"if err := pm.LogoutProfile(id); err != nil {\n\tif strings.Contains(err.Error(), \"does not exist\") {\n\t\t// treat as logged out; refresh UI list\n\t} else {\n\t\t// real I/O or parse failure: inspect the file\n\t}\n}","preventionTips":["Refresh the profile list before acting on cached entries","On fresh installs, complete a login before exposing logout","Avoid acting twice on the same list entry without refreshing in between"],"tags":["android","go","profile","filesystem"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}