From a61495f5ef7c2e6c26b0e607973ee92d83fbae01 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sat, 30 May 2026 18:03:21 +0000 Subject: [PATCH] =?UTF-8?q?fix(api):=20export=20endpoint=20returns=20409?= =?UTF-8?q?=20when=20QA=20gate=20blocks=20(FU-6=20UX=20=E2=80=94=20avoid?= =?UTF-8?q?=20false=20success=20toast)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- web/app.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/web/app.py b/web/app.py index a0398eb..3f241d7 100644 --- a/web/app.py +++ b/web/app.py @@ -3170,10 +3170,25 @@ async def api_export_docx(case_number: str, background_tasks: BackgroundTasks): (markdown body + download link) to the linked issue. """ result = await drafting_tools.export_docx(case_number) - try: - data = json.loads(result) - except json.JSONDecodeError: - raise HTTPException(500, result) + if isinstance(result, dict): + data = result + else: + try: + data = json.loads(result) + except (json.JSONDecodeError, TypeError): + # export_docx can also return a plain (non-JSON) string, e.g. + # "תיק ... לא נמצא." — surface it as a 500 with the raw text. + raise HTTPException(500, str(result)) + + # FU-6: a QA gate (or another error) can block the export. export_docx + # signals this with status == "error". Returning the existing 200 here + # would let the UI show a false "exported successfully" toast, so we map + # a block to 409 Conflict carrying the Hebrew message + failed_gates. + if isinstance(data, dict) and data.get("status") == "error": + detail = {"message": data.get("message", "ייצוא נחסם.")} + if data.get("failed_gates"): + detail["failed_gates"] = data["failed_gates"] + raise HTTPException(409, detail) # Notify the Paperclip plugin to attach the final-decision document. docx_filename = (