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
- Client-side: skip the import call when sessions is empty
- Fix the upstream export/parse step that produced an empty list
- 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
- Guard the call with `if sessions:`
- Log when an export yields zero sessions — it usually means an upstream parse bug
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
- Unsupported import source: {value!r}
- Too many sessions in one request (max {_MAX_SESSIONS_PER_REQ
- Archive '{sanitized_filename}' exceeds maximum size limit of
- Rejected archive '{sanitized_filename}': {exc}
- '{sanitized_filename}' is not a valid zip archive.
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/223320e358235a7c.
Report an issue: GitHub.