HKUDS/DeepTutor · warning · ValueError
Unsupported import source: {value!r}
Error message
Unsupported import source: {value!r} What it means
Pydantic ValidationError raised by the ChatHistoryImportRequest 'source' field validator when the supplied source is not in _ALLOWED_SOURCES after strip+lowercase normalization. FastAPI turns this into a 422 with the message in the errors array.
Source
Thrown at deeptutor/api/routers/imports.py:70
updated_at: float
messages: list[ImportedMessage] = Field(default_factory=list)
class ChatHistoryImportRequest(BaseModel):
source: str = Field(..., min_length=1)
# All sessions in one request belong to one agent (a named, scoped slice of
# 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]] = []
View on GitHub (pinned to 3e82f13042)
Solutions
- Read the 422 response — it echoes the allowed values via the message
- Check _ALLOWED_SOURCES in deeptutor/api/routers/imports.py for the current set
- Send an allowed source string, lowercase (normalization handles case/whitespace, not synonyms)
- File a feature request if a legitimate source is unsupported
Example fix
// before
{"source": "Claude Desktop", "sessions": [...]}
// after
{"source": "claude", "sessions": [...]} Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = {'claude', 'chatgpt', 'file'} # mirror _ALLOWED_SOURCES
source = source.strip().lower()
assert source in ALLOWED, f'unsupported source {source!r}' Type guard
def is_allowed_source(src: str, allowed: set[str]) -> bool:
return (src or '').strip().lower() in allowed Try / catch
try:
client.post('/imports/chat-history', json=payload)
except httpx.HTTPStatusError as e:
if e.response.status_code == 422:
fix_source_field(e.response.json()) # validator message lists the bad value Prevention
- Pin the allowed source list from imports.py at build time
- Normalize case/whitespace client-side before sending
When it happens
Trigger: POST /imports/chat-history with a JSON body whose 'source' is e.g. 'claude ', 'CSV', 'notion', or missing-but-defaulted invalid — anything not in the allowed set.
Common situations: New export format not yet supported, typos in source name, or version change altering the allowed list.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- {exc}
- No fields to update
- Model not configured for agent {self.agent_name}. Please act
- Render failed because local LaTeX is missing. Please avoid T
- Document not found
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/ee9bf9630836e317.
Report an issue: GitHub.