From cbb3896aaa8599d8b83ceef3569d059d32169255 Mon Sep 17 00:00:00 2001 From: DearsisHS Date: Mon, 8 Jun 2026 23:01:28 +0800 Subject: [PATCH] fix(api): guard missing row in SearchService.get_detail (#15622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary `SearchService.get_detail` crashed with `AttributeError` (HTTP 500) when no matching row existed, because it called `.first().to_dict()` before the `if not search` guard — making that guard dead code. ## Root cause `.first()` returns `None` when the query matches nothing (deleted search app, or joined `User` not `VALID`). `None.to_dict()` raises before the guard runs. ## Fix ```diff .first() - .to_dict() ) if not search: return {} - return search + return search.to_dict() ``` Guard the `None` first, then serialize — restoring the intended `{}` "not found" return that every caller (`search_api`, `bot_api`, `chat_api`, `dataset_api_service`) already handles. ## Files changed - `api/db/services/search_service.py` ## Verification - `ruff check` — clean - Logic: `.first()` → `None` now hits `return {}` instead of `None.to_dict()`. Local full pytest not run (heavy RAG deps); CI validates. ## Note Implemented with LLM assistance (model: claude-opus-4-8). Closes #15621 Co-authored-by: dearsishs Co-authored-by: Claude Opus 4.8 --- api/db/services/search_service.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/db/services/search_service.py b/api/db/services/search_service.py index 7366a9708b..90d0e0e605 100644 --- a/api/db/services/search_service.py +++ b/api/db/services/search_service.py @@ -72,11 +72,10 @@ class SearchService(CommonService): .join(User, on=((User.id == cls.model.tenant_id) & (User.status == StatusEnum.VALID.value))) .where((cls.model.id == search_id) & (cls.model.status == StatusEnum.VALID.value)) .first() - .to_dict() ) if not search: return {} - return search + return search.to_dict() @classmethod @DB.connection_context()