datawhalechina/hello-agents · warning · HTTPException

Session not found

Error message

Session not found

What it means

Raised by POST /expand (submit) in SentenceExpandAgent when session_store.get_session(request.session_id) returns nothing — the id was never created, expired from the in-memory/typed store, or belongs to a different process. HTTP 404 before any orchestrator work happens.

Source

Thrown at Co-creation-projects/xujikai-SentenceExpandAgent/backend/src/routers/expand.py:72

@router.post("/session/submit", response_model=AgentResponse)
async def submit_sentence(request: SubmitRequest) -> AgentResponse:
    """
    提交用户扩写句子,返回点评和下一阶段提问(手动模式)
    
    Args:
        request: 提交请求,包含会话 ID 和用户句子
        
    Returns:
        AgentResponse: 智能体响应
    """
    # 获取会话存储
    session_store = get_session_store()
    
    # 获取会话
    session = session_store.get_session(request.session_id)
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")
    
    # 获取 Orchestrator
    orchestrator = get_orchestrator()
    
    # 处理用户输入
    response = orchestrator.process_user_input(
        session_state=session,
        user_sentence=request.user_sentence
    )
    
    # 更新会话
    session_store.update_session(session)
    
    return response


@router.get("/session/{session_id}/auto")
async def auto_mode_stream(session_id: str) -> StreamingResponse:

View on GitHub (pinned to 606a07d341)

Solutions

  1. On 404, create a fresh session and resubmit the sentence
  2. Align the store TTL with realistic conversation length or persist sessions (Redis/DB) if restarts are expected
  3. Run a single worker or share the session store across workers so create/submit hit the same state

Example fix

# before
resp = client.post('/expand', json={'session_id': sid, 'user_sentence': s})
# after
resp = client.post('/expand', json={'session_id': sid, 'user_sentence': s})
if resp.status_code == 404:
    sid = client.post('/expand/session').json()['session_id']
    resp = client.post('/expand', json={'session_id': sid, 'user_sentence': s})
Defensive patterns

Strategy: fallback

Validate before calling

resp = await fetch(`/expand/session/${sid}`, {method: 'HEAD'});
if (resp.status === 404) sid = await createSession(); // recreate before submit

Try / catch

let resp = await submit(sid, sentence);
if (resp.status === 404) {
  sid = await createSession();
  resp = await submit(sid, sentence);
}

Prevention

When it happens

Trigger: POST /expand with a session_id never returned by the create-session endpoint; server restarted so the in-memory session store lost all sessions (TTL expiry); session_id from a different backend instance behind a load balancer without sticky sessions.

Common situations: Client keeps a session id longer than the store TTL; backend redeploy mid-conversation; multiple uvicorn workers each with their own get_session_store() global so the create and submit land on different workers.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/3a1fcb8c7522efc7. Report an issue: GitHub.