{"record":{"id":"b6199ca9f888c306","repo":"SillyTavern/SillyTavern","slug":"forbidden-b6199c","errorCode":null,"errorMessage":"Forbidden","messagePattern":"Forbidden","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"src/endpoints/users-private.js","lineNumber":38,"sourceCode":"            console.error('Session not available');\n            return response.sendStatus(500);\n        }\n\n        request.session.handle = null;\n        request.session.csrfToken = null;\n        request.session.version = null;\n        request.session = null;\n        return response.sendStatus(204);\n    } catch (error) {\n        console.error(error);\n        return response.sendStatus(500);\n    }\n});\n\nrouter.get('/me', async (request, response) => {\n    try {\n        if (!request.user) {\n            return response.sendStatus(403);\n        }\n\n        const user = request.user.profile;\n        const viewModel = {\n            handle: user.handle,\n            name: user.name,\n            avatar: await getUserAvatar(user.handle),\n            admin: user.admin,\n            password: !!user.password,\n            created: user.created,\n        };\n\n        return response.json(viewModel);\n    } catch (error) {\n        console.error(error);\n        return response.sendStatus(500);\n    }\n});","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/SillyTavern/SillyTavern/blob/8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8/src/endpoints/users-private.js#L20-L56","documentation":"Returned as HTTP 403 by GET /api/users/me when request.user is falsy (users-private.js:37). The route relies on an authentication middleware that populates request.user; if no middleware authenticated the caller, request.user is undefined and the endpoint refuses to return profile data. This is the standard 'not authenticated' response for the /me endpoint.","triggerScenarios":"Calling GET /api/users/me without a valid session cookie; the auth middleware did not run or did not set request.user; the session expired between page load and the /me fetch.","commonSituations":"Cookie expired or was cleared; auth middleware misconfigured or skipped for this route in tests; a proxy rewrote the path so the request bypassed the auth middleware; CSRF or session version mismatch caused the auth middleware to leave request.user unset.","solutions":["Ensure the caller is logged in and sends the session cookie.","Confirm the authentication middleware is mounted before the users-private router for GET routes too.","On 403, redirect the user to the login page rather than retrying blindly."],"exampleFix":"// before — calling /me with no credentials\nfetch('/api/users/me')\n// after\nif (!hasSessionCookie()) { location.href = '/login'; return; }\nfetch('/api/users/me', { credentials: 'same-origin' })","handlingStrategy":"validation","validationCode":"// only call /me when we expect to be authenticated\nasync function getMe() {\n  const res = await fetch('/api/users/me', { credentials:'same-origin' });\n  if (res.status === 403) { location.href = '/login'; return null; }\n  return res.json();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Send credentials: 'same-origin' so the session cookie is included.","Treat 403 from /me as 'session expired' and redirect to login.","Confirm the auth middleware runs on GET routes for the users-private router."],"tags":["http-403","authentication","authorization","user-private","middleware"],"backgroundTag":null,"analyzedSha":"8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8","analyzedAt":"2026-08-13T07:48:40.832Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}