{"record":{"id":"9b18ee39d4757a0d","repo":"datawhalechina/hello-agents","slug":"error-9b18ee","errorCode":null,"errorMessage":"会话不存在或已过期","messagePattern":"会话不存在或已过期","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"Co-creation-projects/afei-GuessWhoAmI/backend/main.py","lineNumber":90,"sourceCode":")\n\n# Configure CORS\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"],\n)\n\n# Global session storage: session_id -> (GameSession, HistoricalFigureAgent)\nactive_sessions: Dict[str, tuple] = {}\n\n# Helper functions\ndef get_session_pair(session_id: str):\n    \"\"\"Get game session and agent, raise exception if not found\"\"\"\n    if session_id not in active_sessions:\n        raise HTTPException(\n            status_code=status.HTTP_404_NOT_FOUND,\n            detail=\"会话不存在或已过期\"\n        )\n    return active_sessions[session_id]\n\ndef create_response(success: bool, message: str, data: dict = None, error: str = None) -> GameResponse:\n    \"\"\"Create standardized response\"\"\"\n    return GameResponse(\n        success=success,\n        message=message,\n        data=data,\n        error=error\n    )\n\n# API endpoints\n@app.get(\"/\")\nasync def root():\n    \"\"\"Root endpoint\"\"\"","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/afei-GuessWhoAmI/backend/main.py#L72-L108","documentation":"FastAPI HTTPException 404 raised by get_session_pair when a session_id is not a key in the in-memory active_sessions dict. Sessions live only in process memory — there is no persistence and no TTL, so 'expired' really means 'gone': server restart, session never created, or id typo. Multi-worker deployments (uvicorn --workers N) make this frequent because session created on worker A is invisible to worker B.","triggerScenarios":"Client calls /api/game/ask or similar with a session_id from before a server restart; typo'd or truncated UUID; calling an endpoint before POST /api/game/start; load balancer routing the second request to a different worker; long-running game where the process restarted on deploy.","commonSituations":"Dev server auto-reloading on file change (kills all sessions); Docker container redeploy; scaling to multiple replicas behind a load balancer; frontend keeping a stale session_id in localStorage across days.","solutions":["Client should treat 404 on this endpoint as 'session lost' and transparently call /api/game/start to create a new session","If running multiple workers, pin sessions with sticky routing or move session state to Redis","Disable auto-reload in any long-game deployment (uvicorn --reload off)","Verify the session_id matches the exact UUID returned by /api/game/start (no truncation, no encoding issues)"],"exampleFix":"# before (client pseudocode)\nresp = post('/api/game/ask', {'session_id': sid, ...})\nif resp.status_code != 200: raise\n\n# after\nresp = post('/api/game/ask', {'session_id': sid, ...})\nif resp.status_code == 404 and '会话不存在' in resp.json()['detail']:\n    # session lost (restart / other worker) — restart the game\n    start = post('/api/game/start').json()\n    sid = start['data']['session_id']\n    resp = post('/api/game/ask', {'session_id': sid, ...})","handlingStrategy":"fallback","validationCode":"# client-side: confirm session still valid before a long interaction\nasync def ensure_session(sid: str | None) -> str:\n    if sid and (await client.get(f'/api/game/state/{sid}')).status_code == 200:\n        return sid\n    start = (await client.post('/api/game/start')).json()\n    return start['data']['session_id']","typeGuard":null,"tryCatchPattern":"from fastapi import HTTPException\n\ntry:\n    session, agent = get_session_pair(session_id)\nexcept HTTPException as e:\n    if e.status_code == 404:\n        # transparent restart for the player\n        return create_response(False, \"会话已失效，请重新开始\", error=\"SESSION_LOST\")\n    raise","preventionTips":["Client: on 404 detail '会话不存在或已过期', auto-call /api/game/start and resume","Run a single worker or move session state to Redis if you scale out","Disable --reload in deployments; restarts wipe in-memory sessions"],"tags":["fastapi","session","http-404","in-memory-state","multi-worker"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}