HKUDS/DeepTutor · warning · HTTPException

Too many sessions in one request (max {_MAX_SESSIONS_PER_REQ

Error message

Too many sessions in one request (max {_MAX_SESSIONS_PER_REQUEST})

What it means

413 raised by POST /imports/chat-history when payload.sessions exceeds _MAX_SESSIONS_PER_REQUEST, a bulk-import guard preventing oversized single requests.

Source

Thrown at deeptutor/api/routers/imports.py:79

    agent_id: str = Field(default="", max_length=256)
    agent_name: str = Field(default="", max_length=256)
    sessions: list[ImportedSession] = Field(default_factory=list)

    @field_validator("source")
    @classmethod
    def _normalize_source(cls, value: str) -> str:
        normalized = (value or "").strip().lower()
        if normalized not in _ALLOWED_SOURCES:
            raise ValueError(f"Unsupported import source: {value!r}")
        return normalized


@router.post("/chat-history")
async def import_chat_history(payload: ChatHistoryImportRequest) -> dict[str, Any]:
    if not payload.sessions:
        raise HTTPException(status_code=400, detail="No sessions to import")
    if len(payload.sessions) > _MAX_SESSIONS_PER_REQUEST:
        raise HTTPException(
            status_code=413,
            detail=f"Too many sessions in one request (max {_MAX_SESSIONS_PER_REQUEST})",
        )

    store = get_sqlite_session_store()
    imported = 0
    skipped = 0
    results: list[dict[str, Any]] = []

    for incoming in payload.sessions:
        # Drop content-less rows (e.g. tool-only turns the adapter could not
        # reduce to text) so the transcript stays a clean human conversation.
        messages = [m for m in incoming.messages if (m.content or "").strip()]
        if not messages:
            skipped += 1
            results.append(
                {"external_id": incoming.external_id, "imported": False, "reason": "empty"}
            )

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Read the detail to get the max, then split sessions into batches of at most that size
  2. Add client-side chunking before import
  3. Verify the server constant (or raise it via config if appropriate) in deeptutor/api/routers/imports.py

Example fix

# before
resp = post('/imports/chat-history', json={'source':'claude','sessions':all_sessions})
# after
MAX = 200
for i in range(0, len(all_sessions), MAX):
    post('/imports/chat-history', json={'source':'claude','sessions':all_sessions[i:i+MAX]})
Defensive patterns

Strategy: validation

Validate before calling

MAX = 200  # keep in sync with _MAX_SESSIONS_PER_REQUEST
for i in range(0, len(sessions), MAX):
    import_batch(sessions[i:i + MAX])

Try / catch

resp = client.post('/imports/chat-history', json=payload)
if resp.status_code == 413:
    max_n = int(re.search(r'max (\d+)', resp.text).group(1))
    for i in range(0, len(sessions), max_n):
        client.post('/imports/chat-history', json={**payload, 'sessions': sessions[i:i + max_n]})

Prevention

When it happens

Trigger: POSTing an import with more sessions than the constant allows (e.g. thousands of sessions in one body).

Common situations: Migrating a large multi-year chat history in a single call; no client-side batching.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/aec80ca3da3e4811. Report an issue: GitHub.