From e84be0d42fba6a50c235aff3cdb0425a85066757 Mon Sep 17 00:00:00 2001 From: Asep Haryana Saputra <90584806+MythEclipse@users.noreply.github.com> Date: Fri, 22 May 2026 20:00:01 +0000 Subject: [PATCH] fix: handle malformed ML service responses Co-Authored-By: Claude Opus 4.7 --- apps/api/src/lib/image-model.test.ts | 6 ++++++ apps/api/src/lib/image-model.ts | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/api/src/lib/image-model.test.ts b/apps/api/src/lib/image-model.test.ts index 1e0193b..1e699d3 100644 --- a/apps/api/src/lib/image-model.test.ts +++ b/apps/api/src/lib/image-model.test.ts @@ -66,6 +66,12 @@ describe('classifyImage', () => { await expect(classifyImage(makeImageFile())).rejects.toThrow('ML service returned 503: Model is not loaded'); }); + test('throws when ML service returns malformed JSON', async () => { + mockFetch(async () => new Response('not-json', { status: 200, headers: { 'content-type': 'application/json' } })); + + await expect(classifyImage(makeImageFile())).rejects.toThrow('Invalid ML service JSON response'); + }); + test('throws when ML service returns an unknown label', async () => { mockFetch(async () => new Response( JSON.stringify({ diff --git a/apps/api/src/lib/image-model.ts b/apps/api/src/lib/image-model.ts index ec310ac..c1fa7f8 100644 --- a/apps/api/src/lib/image-model.ts +++ b/apps/api/src/lib/image-model.ts @@ -74,6 +74,14 @@ async function parseErrorResponse(response: Response): Promise { return response.statusText || 'Unknown error'; } +async function parsePredictionResponse(response: Response): Promise { + try { + return await response.json() as MlPredictionResponse; + } catch (error) { + throw new Error('Invalid ML service JSON response'); + } +} + export async function classifyImage(file: File): Promise { if (file.type !== 'image/jpeg' && file.type !== 'image/png') { throw new Error('File must be JPEG or PNG'); @@ -97,7 +105,7 @@ export async function classifyImage(file: File): Promise { throw new Error(`ML service returned ${response.status}: ${message}`); } - const prediction = await response.json() as MlPredictionResponse; + const prediction = await parsePredictionResponse(response); const predictedLabel = assertKnownLabel(prediction.label); const predictedDisease = DISEASE_BY_LABEL.get(predictedLabel)!;