From 3170fa461484d5cbfdeb63276474caccec729e3a Mon Sep 17 00:00:00 2001 From: pharwasz Date: Wed, 26 Aug 2026 11:00:48 +0100 Subject: [PATCH] fix: handle tip service API errors safely --- src/services/__tests__/tipService.test.ts | 11 +++++++++++ src/services/tipService.ts | 15 +++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/services/__tests__/tipService.test.ts b/src/services/__tests__/tipService.test.ts index d5829f64..5760ce5a 100644 --- a/src/services/__tests__/tipService.test.ts +++ b/src/services/__tests__/tipService.test.ts @@ -50,6 +50,17 @@ describe('tipService', () => { ); }); + it('uses the fallback message when the API error payload is not a string', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: async () => ({ error: { detail: 'Bad request' } }), + }); + + await expect(sendTip({ recipientId: 'user-99', amount: 0.05 })).rejects.toThrow( + 'Unable to send tip.', + ); + }); + it('throws when the API returns an error', async () => { mockFetch.mockResolvedValueOnce({ ok: false, diff --git a/src/services/tipService.ts b/src/services/tipService.ts index eb9f5627..81f7e7d2 100644 --- a/src/services/tipService.ts +++ b/src/services/tipService.ts @@ -25,11 +25,18 @@ export async function sendTip(payload: TipPayload): Promise { }); if (!response.ok) { - const responseBody = (await response.json().catch(() => null)) as { - error?: string; - message?: string; + const errorBody = (await response.json().catch(() => null)) as { + error?: unknown; + message?: unknown; } | null; - const message = responseBody?.error ?? responseBody?.message ?? 'Unable to send tip.'; + + const message = + typeof errorBody?.error === 'string' + ? errorBody.error + : typeof errorBody?.message === 'string' + ? errorBody.message + : 'Unable to send tip.'; + throw new Error(message); }