{"record":{"id":"6ac0cf50420a9465","repo":"transloadit/uppy","slug":"failed-to-get-session","errorCode":null,"errorMessage":"Failed to get session","messagePattern":"Failed to get session","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@uppy/core/src/companion-client/googlePicker.ts","lineNumber":548,"sourceCode":"        setTimeout(() => {\n          signal.removeEventListener('abort', reject)\n          resolve()\n        }, interval * 1000)\n        signal.addEventListener('abort', reject, { once: true })\n      })\n\n      const accessToken = getAccessToken()\n      pickingSession = getPickingSession()\n\n      if (pickingSession != null && accessToken != null) {\n        const headers = getAuthHeader(accessToken)\n\n        // https://developers.google.com/photos/picker/reference/rest/v1/sessions\n        const response = await fetch(\n          `https://photospicker.googleapis.com/v1/sessions/${encodeURIComponent(pickingSession.id)}`,\n          { headers, signal },\n        )\n        if (!response.ok) throw new Error('Failed to get session')\n        const json: PickingSession = await response.json()\n        if (json.mediaItemsSet) {\n          // console.log('User picked!', json)\n          const resolvedPhotos = await resolvePickedPhotos({\n            accessToken,\n            pickingSession,\n            signal,\n          })\n          onPickingSessionClear()\n          onFilesPicked(resolvedPhotos, accessToken)\n        }\n        if (pickingSession.pollingConfig.timeoutIn === '0s') {\n          onPickingSessionClear()\n        }\n      }\n    } catch (err) {\n      if (err instanceof Error && err.name === 'AbortError') {\n        return","sourceCodeStart":530,"sourceCodeEnd":566,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/core/src/companion-client/googlePicker.ts#L530-L566","documentation":"Thrown inside pollPickingSession when the periodic GET to photospicker.googleapis.com/v1/sessions/{id} returns non-OK. This poll is what detects when the user finishes picking photos in the Google-side UI; a failure here breaks the polling loop.","triggerScenarios":"Starting the photos picker (init -> pollPickingSession) and any subsequent poll of the session endpoint failing — invalid session id (expired/already consumed), token revoked, 429/5xx from Google.","commonSituations":"User takes too long and the picking session expires server-side; token revoked by the user mid-flow; network interruption during polling; polling rate hitting quota.","solutions":["Restart the picker flow (a fresh session is created) when this error surfaces","Provide onAccessTokenRequired to keep the token fresh during long picking sessions","Catch the error around showPicker and show a user-facing 'please try again' message","Check the network tab for the exact status (404=session expired, 401=token, 429=quota)"],"exampleFix":"// before\nawait picker.showPicker() // session poll 404 after idle -> Failed to get session\n\n// after\ntry { await picker.showPicker() }\ncatch (err) {\n  if (err.message === 'Failed to get session') {\n    uppy.info('Photo picking timed out. Please try again.', 'error', 5000)\n  }\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"function isGetSessionError(e: unknown): boolean {\n  return e instanceof Error && e.message === 'Failed to get session'\n}","tryCatchPattern":"try { await picker.showPicker() }\ncatch (err) {\n  if (isGetSessionError(err)) {\n    uppy.info('Photo picking timed out. Please try again.', 'error', 5000)\n  }\n}","preventionTips":["Restart (re-create) the picking session on failure","Keep tokens fresh with onAccessTokenRequired","Handle poll failures gracefully — sessions expire if idle"],"tags":["google-picker","google-photos","session-polling","timeout"],"backgroundTag":"google-api-session-expired","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}