From 449be211f23f59f9467b4d66b0a17ea7d7abeef9 Mon Sep 17 00:00:00 2001 From: lekss361 Date: Fri, 15 May 2026 07:36:36 +0300 Subject: [PATCH] fix(frontend): apiFetchWithStatus body stream double-read crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per user report 2026-05-14: 'Failed to execute text on Response: body stream already read' при analyze с non-JSON error response. apiFetchWithStatus делал .json() (consumes stream), потом .text() в catch (FAILS — stream already consumed). Fetch API: body — ReadableStream, consumable один раз. Fix: read text() once → JSON.parse on string. На fail (HTML / non-JSON) оборачиваем в {detail: rawText}. Никаких double-reads. Site-finder cad search больше не крашится на error pages. --- frontend/src/lib/api.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index ff1c5b02..64559e2c 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -47,13 +47,17 @@ export async function apiFetchWithStatus( }, }); let body: unknown = null; - // 204 No Content имеет пустое тело; для всех остальных пытаемся JSON + // 204 No Content имеет пустое тело; для всех остальных читаем как text один раз + // (fetch body stream consumable только один раз — нельзя сначала .json() потом .text()). if (response.status !== 204) { - try { - body = await response.json(); - } catch { - // fallback на text() — может прилететь HTML error page от Caddy - body = { detail: await response.text() }; + const rawText = await response.text(); + if (rawText) { + try { + body = JSON.parse(rawText); + } catch { + // Не JSON (HTML error page от Caddy / 502 / etc) — оборачиваем в detail + body = { detail: rawText }; + } } } if (!response.ok) {