Significant-Gravitas/AutoGPT · warning · HTTPException

Session has no active turn. Start a new turn with POST /stre

Error message

Session has no active turn. Start a new turn with POST /stream.

What it means

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.'

Source

Thrown at autogpt_platform/backend/backend/api/features/chat/routes.py:1732

async def queue_pending_message(
    session_id: str,
    request: QueuePendingMessageRequest,
    user_id: str = Security(auth.get_user_id),
):
    """Queue a follow-up message while the session has an active turn."""
    session = await _validate_and_get_session(session_id, user_id)
    if session.metadata.llm_auth_provider == "codex":
        await enforce_codex_access_http(user_id)
    try:
        turn_in_flight = await is_turn_in_flight(session_id)
    except StreamRegistryUnavailable as exc:
        raise HTTPException(
            status_code=503,
            detail="Chat service degraded, retry shortly",
            headers={"Retry-After": "30"},
        ) from exc
    if not turn_in_flight:
        raise HTTPException(
            status_code=409,
            detail="Session has no active turn. Start a new turn with POST /stream.",
        )
    return await queue_pending_for_http(
        session_id=session_id,
        user_id=user_id,
        message=request.message,
        context=request.context,
        file_ids=request.file_ids,
    )


@router.get(
    "/sessions/{session_id}/messages/pending",
    response_model=PeekPendingMessagesResponse,
    responses={
        404: {"description": "Session not found or access denied"},
    },

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Send the message via POST /chat/stream instead — that starts a new turn.
  2. Client-side: on 409 from queue-pending, transparently fall back to the stream endpoint so the user's message is never lost.
  3. Track turn lifecycle (completion events) and route messages accordingly: active turn -> queue-pending, otherwise -> stream.

Example fix

// before
await post(`/chat/sessions/${id}/queue`, {message}); // 409 when turn done

// after — fall back to starting a new turn
try {
  await post(`/chat/sessions/${id}/queue`, {message});
} catch (e) {
  if (e.status === 409) await post('/chat/stream', {session_id: id, message});
  else throw e;
}
Defensive patterns

Strategy: fallback

Validate before calling

// track turn lifecycle so you pick the right endpoint up front
const inFlight = await isTurnInFlight(sessionId);
await (inFlight
  ? post(`/chat/sessions/${id}/queue`, {message})
  : post('/chat/stream', {session_id: id, message}));

Try / catch

try { await post(`/chat/sessions/${id}/queue`, {message}); } catch (e) {
  if (e.status === 409) return post('/chat/stream', {session_id: id, message}); // turn finished; start a new one
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14). Data as JSON: /api/errors/a919e8e49b79353f. Report an issue: GitHub.