{"record":{"id":"1e435771c00d66d2","repo":"laurent22/joplin","slug":"user-is-not-authenticated-1e4357","errorCode":null,"errorMessage":"User is not authenticated","messagePattern":"User is not authenticated","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/lib/SyncTargetOneDrive.ts","lineNumber":131,"sourceCode":"\t\t\t}\n\t\t\tSetting.setValue(`sync.${this.syncTargetId()}.context`, JSON.stringify(context));\n\t\t}\n\t\tapi.setAccountProperties(accountProperties);\n\t\tconst appDir = await this.api().appDirectory();\n\t\t// the appDir might contain non-ASCII characters\n\t\t// /[^\\u0021-\\u00ff]/ is used in Node.js to detect the unescaped characters.\n\t\t// See https://github.com/nodejs/node/blob/bbbf97b6dae63697371082475dc8651a6a220336/lib/_http_client.js#L176\n\t\t// eslint-disable-next-line prefer-regex-literals -- Old code before rule was applied\n\t\tconst baseDir = RegExp(/[^\\u0021-\\u00ff]/).exec(appDir) !== null ? encodeURI(appDir) : appDir;\n\t\tconst fileApi = new FileApi(baseDir, new FileApiDriverOneDrive(this.api()));\n\t\tfileApi.setSyncTargetId(this.syncTargetId());\n\t\tfileApi.setLogger(this.logger());\n\t\treturn fileApi;\n\t}\n\n\tpublic async initSynchronizer() {\n\t\ttry {\n\t\t\tif (!(await this.isAuthenticated())) throw new Error('User is not authenticated');\n\t\t\treturn new Synchronizer(this.db(), await this.fileApi(), Setting.value('appType'));\n\t\t} catch (error) {\n\t\t\tBaseSyncTarget.dispatch({ type: 'SYNC_REPORT_UPDATE', report: { errors: [error] } });\n\t\t\tthrow error;\n\t\t}\n\n\n\t}\n}\n","sourceCodeStart":113,"sourceCodeEnd":141,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/lib/SyncTargetOneDrive.ts#L113-L141","documentation":"Thrown by SyncTargetOneDrive.initSynchronizer() when isAuthenticated() returns false. Like Dropbox, OneDrive sync requires valid OAuth credentials; without them the Synchronizer is not constructed. The catch block dispatches a SYNC_REPORT_UPDATE with the error before re-throwing, so it surfaces in the sync report UI.","triggerScenarios":"initSynchronizer() calls isAuthenticated() which returns false — token missing, expired, or revoked.","commonSituations":"User selected OneDrive but never finished OAuth; token expired after 90 days of inactivity; token revoked in Microsoft account settings; corporate OneDrive with conditional-access policies blocking the app.","solutions":["Re-run the OneDrive OAuth flow from Joplin's Synchronisation settings.","In your Microsoft account's Connected apps, remove Joplin and re-authorise to get a fresh token.","If on a work/school account, confirm conditional-access/MFA policies allow the Joplin app.","Sync again after a successful authorisation."],"exampleFix":"// before: initSynchronizer() throws; sync report shows 'User is not authenticated'\n// after: Tools -> Synchronisation -> target: OneDrive -> re-authorise -> Synchronise","handlingStrategy":"validation","validationCode":"// Gate sync on OneDrive auth before constructing the synchronizer.\nconst authed = await syncTarget.isAuthenticated();\nif (!authed) throw new Error('OneDrive token missing/expired — re-authorise');","typeGuard":"const isOneDriveAuthed = async (target) => await target.isAuthenticated() === true;","tryCatchPattern":"try { await syncTarget.initSynchronizer(); }\ncatch (e) { if (/User is not authenticated/.test(e.message)) { /* re-run OneDrive OAuth flow */ } else throw e; }","preventionTips":["Check isAuthenticated() in the UI before exposing the 'Synchronise' action.","For work/school accounts, confirm conditional-access policies permit the Joplin client app."],"tags":["sync","onedrive","authentication","oauth"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}