{"record":{"id":"3951922ebbb3b62b","repo":"makeplane/plane","slug":"the-request-s-session-was-deleted-before-the-reque","errorCode":null,"errorMessage":"The request's session was deleted before the request completed. The user may have logged out in a concurrent request, for example.","messagePattern":"The request's session was deleted before the request completed\\. The user may have logged out in a concurrent request, for example\\.","errorType":"exception","errorClass":"SessionInterrupted","httpStatus":null,"severity":"error","filePath":"apps/api/plane/authentication/middleware/session.py","lineNumber":76,"sourceCode":"                if request.session.get_expire_at_browser_close():\n                    max_age = None\n                    expires = None\n                else:\n                    # Use different max_age based on whether it's an admin cookie\n                    if is_admin_path:\n                        max_age = settings.ADMIN_SESSION_COOKIE_AGE\n                    else:\n                        max_age = request.session.get_expiry_age()\n\n                    expires_time = time.time() + max_age\n                    expires = http_date(expires_time)\n\n                # Save the session data and refresh the client cookie.\n                if response.status_code < 500:\n                    try:\n                        request.session.save()\n                    except UpdateError:\n                        raise SessionInterrupted(\n                            \"The request's session was deleted before the \"\n                            \"request completed. The user may have logged \"\n                            \"out in a concurrent request, for example.\"\n                        )\n                    response.set_cookie(\n                        cookie_name,\n                        request.session.session_key,\n                        max_age=max_age,\n                        expires=expires,\n                        domain=settings.SESSION_COOKIE_DOMAIN,\n                        path=settings.SESSION_COOKIE_PATH,\n                        secure=settings.SESSION_COOKIE_SECURE or None,\n                        httponly=settings.SESSION_COOKIE_HTTPONLY or None,\n                        samesite=settings.SESSION_COOKIE_SAMESITE,\n                    )\n        return response\n","sourceCodeStart":58,"sourceCodeEnd":93,"githubUrl":"https://github.com/makeplane/plane/blob/1c8a60f858d8472aa56e29994ec1c7926da2c6ce/apps/api/plane/authentication/middleware/session.py#L58-L93","documentation":"SessionInterrupted (Django built-in, re-raised at session.py:76) is raised when request.session.save() throws UpdateError — meaning the session record was deleted from the store between the start of the request and the response phase. The supplied message explains the canonical cause: the user logged out (or the session expired/was purged) in a concurrent request.","triggerScenarios":"process_response saves the session only when status_code < 500 and the session is modified/non-empty. If the underlying session key was already removed (logout in another tab, cache eviction, Redis flush), SessionStore.save() raises UpdateError and the middleware converts it to SessionInterrupted (HTTP 500).","commonSituations":"User clicks logout in one tab while another long-running request is in flight; aggressive Redis eviction/memory pressure dropping session keys; multiple concurrent requests where one deletes the session; session backend misconfigured to a flaky store.","solutions":["Treat as transient: the client should re-authenticate (the session no longer exists).","If frequent, check the session store (Redis) health, memory, and eviction policy — keys should not disappear mid-request.","Avoid issuing parallel mutating requests alongside a logout; sequence logout last.","Confirm SESSION_ENGINE points to a durable, low-latency backend."],"exampleFix":"// before: concurrent logout + API call -> SessionInterrupted 500\n// after: client waits for logout to resolve before further calls,\n//       and re-authenticates on 500/session loss","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from django.contrib.sessions.exceptions import SessionInterrupted\n\ntry:\n    response = middleware_get_response(request)\nexcept SessionInterrupted:\n    # session vanished mid-request (concurrent logout / eviction)\n    response = build_reauth_required_response()","preventionTips":["Sequence logout last on the client; do not fire concurrent mutating requests alongside it.","Monitor the session backend (Redis) for eviction/memory pressure.","Use a durable SESSION_ENGINE with adequate maxmemory."],"tags":["session","concurrency","django","redis","authentication"],"backgroundTag":null,"analyzedSha":"1c8a60f858d8472aa56e29994ec1c7926da2c6ce","analyzedAt":"2026-08-12T14:44:31.636Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}