MemPrepMate / PROFILE_SESSION_FIX.md
Christian Kniep
'switching to mmp'
d7c1993

Profile Session Restoration Fix

Problem Summary

When loading the webapp, users encountered the error:

Error: Profile session not found. Please log in again.

Root Cause

The Flask session cache (session["profile_session_id"]) would expire, but the user's profile session still existed in the backend API. The webapp had no fallback mechanism to restore the session from the backend.

Solution

Implemented a session restoration mechanism that automatically queries the backend API when the Flask session cache expires.

Files Changed

  1. webapp/src/services/session_helper.py (new file)

    • ensure_profile_session(user_id): Queries backend API for existing profile session or creates new one
    • get_or_restore_profile_session(user_id, cached_session_id): Returns cached ID or restores from backend
  2. webapp/src/routes/contacts.py (2 locations updated)

    • Line ~414: In send_message() - replaced simple cache check with restoration logic
    • Line ~537: In add_fact() - replaced simple cache check with restoration logic

How It Works

Before (would fail):

profile_session_id = session.get("profile_session_id")
if not profile_session_id:
    flash("Error: Profile session not found. Please log in again.", "warning")
    return redirect(...)

After (auto-restores):

try:
    profile_session_id = get_or_restore_profile_session(
        user_id=user_id,
        cached_session_id=session.get("profile_session_id")
    )
    # Update Flask session cache
    session["profile_session_id"] = profile_session_id
except Exception as e:
    flash("Error: Unable to initialize profile session. Please log in again.", "warning")
    logger.error(f"Failed to restore profile_session_id for user {user_id}: {e}")
    return redirect(...)

Restoration Flow

  1. Cache Hit: If profile_session_id exists in Flask session β†’ return immediately (fast path)

  2. Cache Miss: If Flask session expired:

    • Call backend_api.list_sessions(user_id=user_id)
    • Search for session with contact_id="user-profile"
    • If found β†’ return existing session_id and update Flask cache
    • If not found β†’ create new profile session and return session_id

Benefits

  • Seamless UX: Users no longer need to log out/in when Flask session expires
  • Resilient: Handles backend session persistence correctly
  • Performant: Only queries backend on cache miss (lazy restoration)
  • Logged: All restoration attempts are logged for monitoring

Testing

Manual Test Steps

  1. Start the backend API:

    cd /Users/christian.kniep/src/gitlab.com/qnib-memverge/streamlit/prepmate
    docker compose up -d api
    
  2. Start the webapp:

    cd webapp
    # Set required environment variables
    export FLASK_SECRET_KEY="your-secret-key"
    export HUGGINGFACE_CLIENT_ID="your-client-id"
    export HUGGINGFACE_CLIENT_SECRET="your-client-secret"
    export BACKEND_API_URL="http://localhost:4004"
    
    # Run webapp
    python -m flask run --port 5001
    
  3. Test restoration scenario:

    • Log in via OAuth (creates profile session)
    • Create a contact
    • Clear Flask session cache (delete cookies or session.pop("profile_session_id"))
    • Send a message to the contact
    • Expected: Message sends successfully (profile session restored automatically)
    • Check logs: Should see [SESSION_RESTORE] or [SESSION_CREATE] log entries

Expected Log Output

Cache Miss β†’ Existing Session Found:

[SESSION_RESTORE] Found existing profile session for user test-user: session_id=abc-123

Cache Miss β†’ New Session Created:

[SESSION_CREATE] Creating new profile session for user test-user
[SESSION_CREATE] Created new profile session for user test-user: session_id=def-456

Verify Fix

  1. Check that messages/facts can be sent even after Flask session expires
  2. Check logs for restoration attempts
  3. Verify no more "Profile session not found" errors in normal operation
  4. Confirm profile session is reused (not creating duplicates)

Related Files

Notes

  • The backend API's GetSession method only retrieves sessions, it does not auto-create
  • Profile sessions are identified by contact_id="user-profile" in the backend
  • The fix maintains backward compatibility - existing profile sessions are reused
  • Flask session cache is updated after successful restoration for performance