{"record":{"id":"4303879cb8290a4b","repo":"laurent22/joplin","slug":"this-profile-is-already-active","errorCode":null,"errorMessage":"This profile is already active","messagePattern":"This profile is already active","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/app-mobile/services/profiles/index.ts","lineNumber":58,"sourceCode":"\tif (!isSubProfile) return `joplin${suffix}.sqlite`;\n\treturn `joplin-${profile.id}${suffix}.sqlite`;\n};\n\nexport const loadProfileConfig = async () => {\n\treturn libLoadProfileConfig(getProfilesConfigPath());\n};\n\nexport const saveProfileConfig = async (profileConfig: ProfileConfig) => {\n\tawait libSaveProfileConfig(getProfilesConfigPath(), profileConfig);\n\tdispatch_({\n\t\ttype: 'PROFILE_CONFIG_SET',\n\t\tvalue: profileConfig,\n\t});\n};\n\nexport const switchProfile = async (profileId: string) => {\n\tconst config = await loadProfileConfig();\n\tif (config.currentProfileId === profileId) throw new Error('This profile is already active');\n\n\tconfig.currentProfileId = profileId;\n\tawait saveProfileConfig(config);\n\tshim.restartApp();\n};\n","sourceCodeStart":40,"sourceCodeEnd":64,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-mobile/services/profiles/index.ts#L40-L64","documentation":"Thrown by `switchProfile` in the mobile profile service when the requested `profileId` is already the `currentProfileId` in the loaded config. Switching to the active profile is a no-op and would pointlessly `restartApp`, so it is rejected up front.","triggerScenarios":"Calling `switchProfile(profileId)` where `profileId === (await loadProfileConfig()).currentProfileId`. Commonly hit from the profile switcher UI when the user taps the currently-selected profile.","commonSituations":"UI bug that does not mark/highlight the active profile row; double-tap on the active row; programmatic switch issued right after a previous switch but before `restartApp` takes effect.","solutions":["In the UI, disable or mark the active profile row as non-selectable.","Pre-check: `if (profileId === currentProfileId) return;` before calling `switchProfile`.","Idempotency: catch the error and treat it as success when the goal state is already met."],"exampleFix":"// before\nawait switchProfile(profileId);\n\n// after\nconst config = await loadProfileConfig();\nif (config.currentProfileId !== profileId) {\n  await switchProfile(profileId);\n}","handlingStrategy":"validation","validationCode":"const config = await loadProfileConfig();\nif (config.currentProfileId === profileId) {\n  logger.info('Profile already active; skipping switch');\n  return;\n}\nawait switchProfile(profileId);","typeGuard":"null","tryCatchPattern":"try {\n  await switchProfile(profileId);\n} catch (error) {\n  if (/already active/i.test(error.message)) return;\n  throw error;\n}","preventionTips":["Disable the active profile row in the switcher UI.","Pre-check currentProfileId before calling switchProfile.","Avoid issuing a second switch before restartApp completes."],"tags":["profiles","validation","mobile","precondition"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}