abi/screenshot-to-code · error · HTTPException

Session not found

Error message

Session not found

What it means

Raised by POST /eval-sessions/{session_id}/activate (404) when eval_sessions.get_session() returns None — the session id is unknown. Sessions live in the eval-sessions store; an id can become stale when the session was deleted, the store was reset, or the backend restarted with ephemeral/in-memory session storage.

Source

Thrown at backend/routes/eval_sets.py:218

async def create_eval_session(request: CreateEvalSessionRequest) -> EvalSessionModel:
    try:
        eval_sets.get_set(request.eval_set)
    except eval_sets.InvalidSetNameError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except eval_sets.EvalSetNotFoundError:
        raise HTTPException(
            status_code=404, detail=f"Eval set not found: {request.eval_set}"
        )
    session = eval_sessions.create_session(request.eval_set, request.name)
    return _session_to_model(session)


@router.post(
    "/eval-sessions/{session_id}/activate", response_model=EvalSessionModel
)
async def activate_eval_session(session_id: str) -> EvalSessionModel:
    if eval_sessions.get_session(session_id) is None:
        raise HTTPException(status_code=404, detail="Session not found")
    session = eval_sessions.activate_session(session_id)
    assert session is not None
    return _session_to_model(session)


def _is_stale_running(status: str, created_at: str) -> bool:
    if status != "running":
        return False
    try:
        started = datetime.fromisoformat(created_at)
    except ValueError:
        return True
    return datetime.now() - started > _STALE_RUNNING_AFTER


@router.get(
    "/eval-sessions/{session_id}/matrix", response_model=SessionMatrixResponse
)

View on GitHub (pinned to d026163f58)

Solutions

  1. GET /eval-sessions to list current sessions and activate one of those ids.
  2. Create a new session via POST /eval-sessions if the old one is gone.
  3. Refresh session state after backend restarts rather than caching ids indefinitely.

Example fix

# before
requests.post(url + f"/eval-sessions/{sid}/activate")  # 404

# after
sessions = requests.get(url + "/eval-sessions").json()["sessions"]
if not any(s["session_id"] == sid for s in sessions):
    sid = requests.post(url + "/eval-sessions", json={"eval_set": set_name}).json()["session_id"]
requests.post(url + f"/eval-sessions/{sid}/activate")
Defensive patterns

Strategy: validation

Validate before calling

sessions = requests.get(url + "/eval-sessions").json()["sessions"]
known = {s["session_id"] for s in sessions}
if session_id not in known:
    raise LookupError(f"session {session_id!r} unknown; active={sessions}")

Type guard

def session_exists(session_id: str, sessions: list[dict]) -> bool:
    return any(s.get("session_id") == session_id for s in sessions)

Try / catch

resp = requests.post(url + f"/eval-sessions/{session_id}/activate")
if resp.status_code == 404:
    new = requests.post(url + "/eval-sessions", json={"eval_set": set_name}).json()
    resp = requests.post(url + f"/eval-sessions/{new['session_id']}/activate")
resp.raise_for_status()

Prevention

When it happens

Trigger: Activating a session id from an old list, after the sessions store was cleared, or with a typo'd/truncated id. The check is a simple lookup before activate_session() runs.

Common situations: UI holds a session id across a backend restart; sessions pruned by cleanup; concurrent activation of a since-deleted session.

Related errors


AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14). Data as JSON: /api/errors/495c6dc036ab8c95. Report an issue: GitHub.