{"record":{"id":"cbaf07ffc7bb98a5","repo":"alyssaxuu/screenity","slug":"not-authenticated-with-screenity","errorCode":null,"errorMessage":"Not authenticated with Screenity","messagePattern":"Not authenticated with Screenity","errorType":"exception","errorClass":"Error","httpStatus":401,"severity":"error","filePath":"src/pages/CloudRecorder/bunnyTusUploader.js","lineNumber":924,"sourceCode":"        if (existingMap?.videoId && existingMap?.mediaId) {\n          this.videoId = existingMap.videoId;\n          this.mediaId = existingMap.mediaId;\n          this.journalKey = this.getJournalKey(this.mediaId);\n          this.debugLog(\"Reusing Bunny video from map\", {\n            projectId,\n            sceneId,\n            type,\n            mediaId: this.mediaId,\n          });\n        }\n      }\n\n      if (!this.videoId || !this.mediaId) {\n        const { authenticated, user } = await new Promise((resolve) => {\n          chrome.runtime.sendMessage({ type: \"check-auth-status\" }, resolve);\n        });\n\n        if (!authenticated) throw new Error(\"Not authenticated with Screenity\");\n\n        const { screenityToken } = await chrome.storage.local.get([\n          \"screenityToken\",\n        ]);\n\n        this.userToken = screenityToken;\n\n        if (!this.userToken) {\n          throw new Error(\"Missing user token for saving upload metadata\");\n        }\n\n        // Retry transient failures so a backend blip doesn't abort the\n        // recording. A 4xx is a real rejection, so don't retry it.\n        let res = null;\n        // This POST gates capture start (canBeginRecording waits on uploader\n        // init), so its server time is start latency.\n        const endCreatePost = perfSpan(\"Uploader POST /bunny/videos\", { type });\n        // Also kept on the instance: the perf timeline is capped and evicts","sourceCodeStart":906,"sourceCodeEnd":942,"githubUrl":"https://github.com/alyssaxuu/screenity/blob/512606387b8d07dda5e63bb428bd063f0a2a3ed0/src/pages/CloudRecorder/bunnyTusUploader.js#L906-L942","documentation":"When initialize() cannot resolve videoId/mediaId from `reuse`, the resume journal, or the stored video map, it must create a new Bunny video on the backend. Before that POST it asks the extension background (chrome.runtime.sendMessage({type:'check-auth-status'})) whether the user is signed in to Screenity; if the background reports authenticated === false, initialize() throws because creating the video requires a signed-in session. This gates upload creation behind extension sign-in.","triggerScenarios":"Uploader initialize() reached the 'no existing video' path (no reuse, no journal, no video map) AND the background's check-auth-status responded authenticated:false — i.e. sendMessage succeeded but the user is logged out or the background auth state was never populated.","commonSituations":"User signed out of Screenity (or never signed in) and then started a cloud recording; extension background service worker restarted and lost cached auth state; auth cookie/token expired between sign-in and recording start.","solutions":["Have the user sign in to Screenity (complete the extension auth flow) before starting a recording, then retry initialize().","Verify the background service worker handles 'check-auth-status' and reports the correct authenticated value; if it responds undefined, check for a missing/throwing handler.","If the user appears signed in, clear extension auth state and re-run the sign-in flow to refresh an expired session/cookie.","Retry after refreshing the token in chrome.storage.local (screenityToken) in case the background state was stale."],"exampleFix":"// before\nawait uploader.initialize({ projectId, sceneId, type });\n// after\nconst { authenticated } = await chrome.runtime.sendMessage({ type: \"check-auth-status\" });\nif (!authenticated) {\n  await promptUserSignIn(); // run the Screenity auth flow first\n}\nawait uploader.initialize({ projectId, sceneId, type });","handlingStrategy":"try-catch","validationCode":"const { authenticated } = await chrome.runtime.sendMessage({ type: 'check-auth-status' });\nif (!authenticated) {\n  await launchSignInFlow(); // must complete before initializing the uploader\n}","typeGuard":"function isAuthStatus(res) {\n  return res != null && typeof res.authenticated === 'boolean';\n}","tryCatchPattern":"try {\n  await uploader.initialize({ projectId, sceneId, type });\n} catch (err) {\n  if (String(err?.message).includes('Not authenticated with Screenity')) {\n    await promptUserSignIn(); // UI sign-in, then retry once\n    await uploader.initialize({ projectId, sceneId, type });\n  } else throw err;\n}","preventionTips":["Gate the record button on a known-good check-auth-status result before starting capture.","Handle the background responding undefined (missing handler) rather than treating it as authenticated.","Proactively refresh auth state on extension service-worker startup.","Surface a sign-in prompt instead of silently starting a recording."],"tags":["authentication","extension","chrome-runtime","unauthorized"],"backgroundTag":"not-authenticated","analyzedSha":"512606387b8d07dda5e63bb428bd063f0a2a3ed0","analyzedAt":"2026-09-02T20:59:09.419Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}