{"record":{"id":"47de5786abb18eb3","repo":"payloadcms/payload","slug":"cannot-refresh-token-user-not-authenticated","errorCode":null,"errorMessage":"Cannot refresh token: user not authenticated","messagePattern":"Cannot refresh token: user not authenticated","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/payload/src/auth/serverFunctions/refresh.ts","lineNumber":30,"sourceCode":"  config: MaybePromise<SanitizedConfig>\n  serverAdapter: ServerAdapter\n}\n\n/**\n * Refreshes the current user's auth token and rewrites the cookie through the\n * supplied `serverAdapter`, so the function is framework-agnostic; each adapter\n * binds its own.\n */\nexport async function refresh({\n  config,\n  serverAdapter,\n}: RefreshArgs): Promise<{ message: string; success: boolean }> {\n  const payload = await getPayload({ config, cron: true })\n  const headers = await serverAdapter.getHeaders()\n  const result = await payload.auth({ headers })\n\n  if (!result.user) {\n    throw new Error('Cannot refresh token: user not authenticated')\n  }\n\n  const existingCookie = await getExistingAuthToken({\n    cookiePrefix: payload.config.cookiePrefix,\n    serverAdapter,\n  })\n\n  if (!existingCookie) {\n    return { message: 'No valid token found to refresh', success: false }\n  }\n\n  const collection: CollectionSlug | undefined = result.user.collection\n  const collectionConfig = payload.collections[collection]\n\n  if (!collectionConfig?.config.auth) {\n    throw new Error(`No auth config found for collection: ${collection}`)\n  }\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/auth/serverFunctions/refresh.ts#L12-L48","documentation":"The `refresh` server function calls `payload.auth({ headers })`; if the returned `result.user` is null/undefined it throws this. There is no authenticated session to refresh: the request carried no valid (or already expired/destroyed) auth token.","triggerScenarios":"Calling `refresh({ config, serverAdapter })` when `serverAdapter.getHeaders()` returns headers with no `payload-token` cookie, an expired token, or a token whose user/session was deleted. The auth lookup resolves to no user.","commonSituations":"Token expired and the client did not re-login; an SSR adapter stripped the cookie; the user was deactivated/deleted; refresh invoked on an already-logged-out session.","solutions":["Guard the `refresh` call behind a session/cookie presence check.","Verify `serverAdapter.getHeaders()` forwards the auth cookie.","If the token expired, call `login` first to obtain a fresh token before refreshing."],"exampleFix":"// before\nawait refresh({ config, serverAdapter })\n// after\nconst authed = await payload.auth({ headers: await serverAdapter.getHeaders() })\nif (!authed.user) {\n  await login({ collection: 'users', config, email, password, serverAdapter })\n} else {\n  await refresh({ config, serverAdapter })\n}","handlingStrategy":"validation","validationCode":"async function hasSessionCookie(serverAdapter) {\n  const headers = await serverAdapter.getHeaders()\n  const cookie = headers.get('cookie') ?? ''\n  return /payload-token=/.test(cookie)\n}\n// before refresh:\nif (!(await hasSessionCookie(serverAdapter))) await redirectToLogin()","typeGuard":"function isAuthenticated(authResult): authResult is { user: Record<string, unknown> } {\n  return !!authResult?.user\n}","tryCatchPattern":"try {\n  await refresh({ config, serverAdapter })\n} catch (e) {\n  if (e instanceof Error && /not authenticated/.test(e.message)) {\n    await redirectToLogin()\n  } else {\n    throw e\n  }\n}","preventionTips":["Guard refresh calls behind a session/cookie check.","Forward cookies through SSR adapters.","Treat refresh failure as a re-login trigger, not a crash."],"tags":["auth","refresh","session","token"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}