{"record":{"id":"535e2ba4d4a3f9b6","repo":"Significant-Gravitas/AutoGPT","slug":"authentication-failed-please-sign-in-again","errorCode":null,"errorMessage":"Authentication failed — please sign in again.","messagePattern":"Authentication failed — please sign in again\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts","lineNumber":35,"sourceCode":"export const COPILOT_COMPLETION_NOTIFICATION = {\n  title: \"AutoGPT\",\n  body: \"Task completed\",\n  icon: \"/notification-icon-192.png\",\n} as const;\n\n/**\n * Returns HTTP headers required for direct backend requests from copilot:\n * - Authorization Bearer token (JWT)\n * - X-Act-As-User-Id impersonation header (if an admin is impersonating a user)\n *\n * Use this for all direct-to-backend fetch/SSE calls so that admin user\n * impersonation works consistently across the entire copilot feature.\n */\nexport async function getCopilotAuthHeaders(): Promise<Record<string, string>> {\n  const { token, error } = await getWebSocketToken();\n  if (error || !token) {\n    console.warn(\"[Copilot] Failed to get auth token:\", error);\n    throw new Error(\"Authentication failed — please sign in again.\");\n  }\n  return {\n    Authorization: `Bearer ${token}`,\n    ...getSystemHeaders(),\n  };\n}\n\n/**\n * Build the document title showing how many sessions are ready.\n * Returns the base title when count is 0.\n */\nexport function formatNotificationTitle(count: number): string {\n  return count > 0\n    ? `(${count}) AutoPilot is ready - ${ORIGINAL_TITLE}`\n    : ORIGINAL_TITLE;\n}\n\n/**","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts#L17-L53","documentation":"Thrown by getCopilotAuthHeaders() in the copilot feature when getWebSocketToken() (a server action from @/lib/auth/actions) returns an error or no token. All direct-to-backend copilot fetch/SSE calls build their Authorization header here, so a failed token fetch aborts every copilot network operation with this message. The underlying cause is almost always an expired Supabase session or a failed server-action round trip, not the copilot backend itself.","triggerScenarios":"Calling getCopilotAuthHeaders() after the Supabase JWT has expired (long-lived tab), when the user's session cookie is missing (signed out in another tab, cleared storage), when the getWebSocketToken server action fails (network error, 5xx, middleware redirect), or when it returns { token: null } because no authenticated user exists.","commonSituations":"Leaving a copilot tab open overnight past JWT expiry; running the frontend against a misconfigured Supabase (wrong NEXT_PUBLIC_SUPABASE_URL/keys); a dev server restart that invalidated cookies; user impersonation flows where the admin session expired; ad-blockers or service workers intercepting the server action.","solutions":["Sign in again (reload and re-authenticate) — the message is accurate; the session is dead.","Check browser network tab for the getWebSocketToken server action call: a non-200 or redirect confirms a Supabase/config issue rather than copilot code.","Verify NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEY in frontend/.env match the project the user signed into.","If it reproduces immediately after login, confirm the Supabase middleware (src/lib/supabase/middleware.ts) is not stripping auth cookies for the copilot route.","As a code-level hardening, catch this error at the call site and redirect to sign-in instead of toasting a generic failure."],"exampleFix":"// before\nconst headers = await getCopilotAuthHeaders(); // throws, copilot fetch dies silently\n\n// after\ntry {\n  const headers = await getCopilotAuthHeaders();\n} catch (e) {\n  window.location.href = \"/login?redirected=copilot\";\n  return;\n}","handlingStrategy":"try-catch","validationCode":"import { getWebSocketToken } from \"@/lib/auth/actions\";\n\nasync function hasCopilotAuth(): Promise<boolean> {\n  const { token, error } = await getWebSocketToken();\n  return !error && !!token;\n}","typeGuard":"function isAuthFailure(err: unknown): boolean {\n  return err instanceof Error && err.message.startsWith(\"Authentication failed\");\n}","tryCatchPattern":"try {\n  const headers = await getCopilotAuthHeaders();\n  // ...fetch\n} catch (error) {\n  if (isAuthFailure(error)) {\n    window.location.href = \"/login\"; // session is unrecoverable client-side\n    return;\n  }\n  throw error;\n}","preventionTips":["Call getCopilotAuthHeaders per-request, never cache the token across long-lived SSE streams.","Proactively refresh the session (supabase.auth.startAutoRefresh) in long-lived copilot tabs.","Route all copilot direct-backend calls through this single helper so auth failures have one catch point."],"tags":["authentication","supabase","copilot","session-expiry","frontend"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}