{"record":{"id":"a919e8e49b79353f","repo":"Significant-Gravitas/AutoGPT","slug":"session-has-no-active-turn-start-a-new-turn-with","errorCode":null,"errorMessage":"Session has no active turn. Start a new turn with POST /stream.","messagePattern":"Session has no active turn\\. Start a new turn with POST /stream\\.","errorType":"http","errorClass":"HTTPException","httpStatus":409,"severity":"warning","filePath":"autogpt_platform/backend/backend/api/features/chat/routes.py","lineNumber":1732,"sourceCode":"async def queue_pending_message(\n    session_id: str,\n    request: QueuePendingMessageRequest,\n    user_id: str = Security(auth.get_user_id),\n):\n    \"\"\"Queue a follow-up message while the session has an active turn.\"\"\"\n    session = await _validate_and_get_session(session_id, user_id)\n    if session.metadata.llm_auth_provider == \"codex\":\n        await enforce_codex_access_http(user_id)\n    try:\n        turn_in_flight = await is_turn_in_flight(session_id)\n    except StreamRegistryUnavailable as exc:\n        raise HTTPException(\n            status_code=503,\n            detail=\"Chat service degraded, retry shortly\",\n            headers={\"Retry-After\": \"30\"},\n        ) from exc\n    if not turn_in_flight:\n        raise HTTPException(\n            status_code=409,\n            detail=\"Session has no active turn. Start a new turn with POST /stream.\",\n        )\n    return await queue_pending_for_http(\n        session_id=session_id,\n        user_id=user_id,\n        message=request.message,\n        context=request.context,\n        file_ids=request.file_ids,\n    )\n\n\n@router.get(\n    \"/sessions/{session_id}/messages/pending\",\n    response_model=PeekPendingMessagesResponse,\n    responses={\n        404: {\"description\": \"Session not found or access denied\"},\n    },","sourceCodeStart":1714,"sourceCodeEnd":1750,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/chat/routes.py#L1714-L1750","documentation":"HTTP 409 from the queue-pending endpoint (routes.py:1732). The endpoint exists ONLY to attach a follow-up message to a currently active turn. It checks is_turn_in_flight(session_id); when false there is nothing to queue onto, so it returns 409 with the corrective action: 'Start a new turn with POST /stream.'","triggerScenarios":"Calling queue-pending after the active turn already completed (or before any turn started) — classic race where the turn finishes between the client seeing 'in flight' and the queue-pending POST landing.","commonSituations":"User types a follow-up right as the agent finishes; client's turn-state subscription lags; retry of a queued message after completion; calling the endpoint on a brand-new session.","solutions":["Send the message via POST /chat/stream instead — that starts a new turn.","Client-side: on 409 from queue-pending, transparently fall back to the stream endpoint so the user's message is never lost.","Track turn lifecycle (completion events) and route messages accordingly: active turn -> queue-pending, otherwise -> stream."],"exampleFix":"// before\nawait post(`/chat/sessions/${id}/queue`, {message}); // 409 when turn done\n\n// after — fall back to starting a new turn\ntry {\n  await post(`/chat/sessions/${id}/queue`, {message});\n} catch (e) {\n  if (e.status === 409) await post('/chat/stream', {session_id: id, message});\n  else throw e;\n}","handlingStrategy":"fallback","validationCode":"// track turn lifecycle so you pick the right endpoint up front\nconst inFlight = await isTurnInFlight(sessionId);\nawait (inFlight\n  ? post(`/chat/sessions/${id}/queue`, {message})\n  : post('/chat/stream', {session_id: id, message}));","typeGuard":null,"tryCatchPattern":"try { await post(`/chat/sessions/${id}/queue`, {message}); } catch (e) {\n  if (e.status === 409) return post('/chat/stream', {session_id: id, message}); // turn finished; start a new one\n  throw e;\n}","preventionTips":["On 409 from queue-pending, transparently fall back to POST /stream so the message is never lost","Subscribe to turn-completion events to keep client turn-state fresh","Treat queue-pending as attach-only; the stream endpoint is the source of truth for new turns"],"tags":["http","chat","race-condition","state-machine","fastapi"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}