From 13eac70cecd6ed5b588f827fac0a28512fe1a55e Mon Sep 17 00:00:00 2001 From: "shakespeare.diy" Date: Tue, 16 Jun 2026 19:49:09 +0700 Subject: [PATCH] fix: improve 400 error logging to surface raw API body Previously, the catch block around response.json() would swallow the actual error body and replace it with a generic "Invalid request" message. Now: - Read response as text() first (never fails) - Log the raw body to console as [Shakespeare API 400] raw body: - Parse JSON from the text string separately - Fallback error message includes the raw body so it's visible in console This will make it easy to diagnose exactly what the Shakespeare API is rejecting (model name, message format, missing field, etc.) Co-authored-by: shakespeare.diy --- src/hooks/useShakespeare.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/hooks/useShakespeare.ts b/src/hooks/useShakespeare.ts index 233c0a2..3f5d643 100644 --- a/src/hooks/useShakespeare.ts +++ b/src/hooks/useShakespeare.ts @@ -109,9 +109,11 @@ async function handleAPIError(response: Response) { } else if (response.status === 402) { throw new Error('Insufficient credits. Please add credits to your account to use premium models, or use the free "tybalt" model.'); } else if (response.status === 400) { + // Read raw text first so we always have the body for logging + const rawBody = await response.text().catch(() => '(unreadable body)'); + console.error('[Shakespeare API 400] raw body:', rawBody); try { - const error = await response.json(); - console.error('[Shakespeare API 400]', JSON.stringify(error)); + const error = JSON.parse(rawBody); if (error.error?.type === 'invalid_request_error') { if (error.error.code === 'minimum_amount_not_met') { throw new Error(`Minimum credit amount is $${error.error.minimum_amount}. Please increase your payment amount.`); @@ -121,11 +123,12 @@ async function handleAPIError(response: Response) { throw new Error('Invalid redirect URL provided for Stripe payment.'); } } - const msg = error.error?.message || error.message || error.details || JSON.stringify(error); + const msg = error.error?.message || error.message || error.details || rawBody; throw new Error(`API 400: ${msg}`); } catch (inner) { if (inner instanceof Error && inner.message.startsWith('API 400:')) throw inner; - throw new Error('Invalid request. Please check your parameters and try again.'); + // Body was not JSON or unrecognised structure — surface the raw body + throw new Error(`API 400: ${rawBody}`); } } else if (response.status === 404) { throw new Error('Resource not found. Please check the payment ID or try again.');