HKUDS/DeepTutor · warning · HTTPException

No sessions to import

Error message

No sessions to import

What it means

400 raised by POST /imports/chat-history when payload.sessions is empty (falsy). The endpoint refuses no-op imports up front rather than returning a misleading success with imported=0.

Source

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

    # a source folder). Empty when the client hasn't adopted the agent model yet
    # — the backend stays backwards-compatible by simply omitting attribution.
    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(

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Client-side: skip the import call when sessions is empty
  2. Fix the upstream export/parse step that produced an empty list
  3. If you genuinely expected sessions, verify the export file was read correctly

Example fix

// before
await client.post('/imports/chat-history', json={'source':'claude','sessions':sessions})
// after
if sessions:
    await client.post('/imports/chat-history', json={'source':'claude','sessions':sessions})
Defensive patterns

Strategy: validation

Validate before calling

if not sessions:
    return  # nothing to import — skip the call entirely

Type guard

def has_sessions(payload: dict) -> bool:
    return bool(payload.get('sessions'))

Try / catch

resp = client.post('/imports/chat-history', json=payload)
if resp.status_code == 400 and 'No sessions' in resp.text:
    return {'imported': 0}

Prevention

When it happens

Trigger: POSTing {"source":"claude","sessions":[]} or omitting the sessions field if it defaults to empty.

Common situations: Upstream export produced zero sessions (filter bug, wrong file parsed) and the client forwards it blindly; test asserting rejection of empty bodies.

Related errors


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