{"record":{"id":"f68870f536948d02","repo":"netbirdio/netbird","slug":"failed-to-read-profile-config-w","errorCode":null,"errorMessage":"failed to read profile config: %w","messagePattern":"failed to read profile config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/android/profile_manager.go","lineNumber":192,"sourceCode":"func (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\n\t// logout semantics: the next login passes it as the login_hint so the IdP\n\t// preselects the account. Removing the profile is what deletes it.\n\tlog.Infof(\"logged out from profile: %s\", id)\n\treturn nil\n}\n","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/android/profile_manager.go#L174-L210","documentation":"profilemanager.ReadConfig could not read or parse the profile's JSON config. The file exists (os.Stat passed) but is unreadable (permissions, I/O error) or its content is not valid config JSON — typically a truncated or corrupted write from an earlier save.","triggerScenarios":"LogoutProfile hits a config file corrupted by an interrupted WriteOutConfig, a hand-edited file, or a read error from failing storage.","commonSituations":"App killed mid-write, disk-full during a previous save, files modified externally, aging flash storage producing read errors.","solutions":["Inspect the file content at configDir/profiles/<id>.json (or netbird.cfg for default)","If corrupt, delete it — the next login recreates the config and the peer re-enrols","Retry after the underlying storage issue is resolved"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Optional pre-check that the config parses, before offering logout\nif _, err := os.Stat(configPath); err == nil {\n\tif data, rerr := os.ReadFile(configPath); rerr == nil && !json.Valid(data) {\n\t\t// corrupt file: quarantine/delete it rather than calling LogoutProfile\n\t}\n}","typeGuard":null,"tryCatchPattern":"if err := pm.LogoutProfile(id); err != nil {\n\tif strings.Contains(err.Error(), \"failed to read profile config\") {\n\t\t// file exists but is unreadable/corrupt: inspect or delete it; next login recreates it\n\t}\n}","preventionTips":["Never hand-edit profile JSON","Keep the app alive through writes so saves are not truncated","On repeated read failures, suspect failing storage and check device health"],"tags":["android","go","profile","json","filesystem"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}