From 3baa990604f1d2bef77b1cfabbc2cecff3137422 Mon Sep 17 00:00:00 2001 From: hzhang Date: Wed, 10 Jun 2026 21:24:14 +0100 Subject: [PATCH] fix(tasks): tolerate out-of-enum task_type/status on read (stop list 500) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TaskResponse inherited task_type: TaskTypeEnum (TaskBase) and declared status: TaskStatusEnum. The tasks table column is a free-form String(32), so a single row whose task_type/status falls outside the strict enum (e.g. seeded rows with task_type='setup' or 'recruit') made pydantic raise a ValidationError while serializing the list — taking down `GET /tasks` / `hf task list` entirely with HTTP 500 (no --status filter, --status open, and --project all 500'd; only filters that happened to exclude the bad rows worked). Override task_type and status as plain str on TaskResponse so reads surface legacy/unknown values verbatim instead of crashing the whole list. Writes stay strict: TaskCreate/TaskBase still use the enums and create is gated by _validate_task_type_subtype (ALLOWED_TASK_TYPES); TaskUpdate still uses the enums. Verified on sim: `hf task list` (and --status open / --project) now return all rows including task_type='setup'/'recruit' instead of 500. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/schemas/schemas.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/schemas/schemas.py b/app/schemas/schemas.py index 79cf582..18dcdcc 100644 --- a/app/schemas/schemas.py +++ b/app/schemas/schemas.py @@ -74,7 +74,15 @@ class TaskUpdate(BaseModel): class TaskResponse(TaskBase): id: int - status: TaskStatusEnum + # Read-side is intentionally lenient: legacy/seeded rows can hold a + # task_type or status outside the strict create-time enums (the column is + # a free-form String(32); e.g. a seeded task_type='setup'). Surfacing them + # as plain strings keeps list endpoints from 500-ing on a single + # out-of-enum row — one bad task used to take down `hf task list` + # entirely. Writes stay strict via TaskCreate/_validate_task_type_subtype + # and TaskUpdate (both still use the enums). + task_type: str = "issue" + status: str task_code: Optional[str] = None code: Optional[str] = None type: Optional[str] = None