makeplane/plane · error · SessionInterrupted

The request's session was deleted before the request complet

Error message

The request's session was deleted before the request completed. The user may have logged out in a concurrent request, for example.

What it means

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.

Source

Thrown at apps/api/plane/authentication/middleware/session.py:76

                if request.session.get_expire_at_browser_close():
                    max_age = None
                    expires = None
                else:
                    # Use different max_age based on whether it's an admin cookie
                    if is_admin_path:
                        max_age = settings.ADMIN_SESSION_COOKIE_AGE
                    else:
                        max_age = request.session.get_expiry_age()

                    expires_time = time.time() + max_age
                    expires = http_date(expires_time)

                # Save the session data and refresh the client cookie.
                if response.status_code < 500:
                    try:
                        request.session.save()
                    except UpdateError:
                        raise SessionInterrupted(
                            "The request's session was deleted before the "
                            "request completed. The user may have logged "
                            "out in a concurrent request, for example."
                        )
                    response.set_cookie(
                        cookie_name,
                        request.session.session_key,
                        max_age=max_age,
                        expires=expires,
                        domain=settings.SESSION_COOKIE_DOMAIN,
                        path=settings.SESSION_COOKIE_PATH,
                        secure=settings.SESSION_COOKIE_SECURE or None,
                        httponly=settings.SESSION_COOKIE_HTTPONLY or None,
                        samesite=settings.SESSION_COOKIE_SAMESITE,
                    )
        return response

View on GitHub (pinned to 1c8a60f858)

Solutions

  1. Treat as transient: the client should re-authenticate (the session no longer exists).
  2. If frequent, check the session store (Redis) health, memory, and eviction policy — keys should not disappear mid-request.
  3. Avoid issuing parallel mutating requests alongside a logout; sequence logout last.
  4. Confirm SESSION_ENGINE points to a durable, low-latency backend.

Example fix

// before: concurrent logout + API call -> SessionInterrupted 500
// after: client waits for logout to resolve before further calls,
//       and re-authenticates on 500/session loss
Defensive patterns

Strategy: try-catch

Try / catch

from django.contrib.sessions.exceptions import SessionInterrupted

try:
    response = middleware_get_response(request)
except SessionInterrupted:
    # session vanished mid-request (concurrent logout / eviction)
    response = build_reauth_required_response()

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12). Data as JSON: /api/errors/3951922ebbb3b62b. Report an issue: GitHub.