diff --git a/app/api/streak/route.ts b/app/api/streak/route.ts index 5586ea02b..dfef264d1 100644 --- a/app/api/streak/route.ts +++ b/app/api/streak/route.ts @@ -513,6 +513,39 @@ export async function GET(request: Request) { } } } + } catch (error: unknown) { + const msg = error instanceof Error ? error.message.toLowerCase() : ''; + const isRateLimit = msg.includes('rate limit'); + const isTimeout = isAbortError(error); + const isValidationError = msg.includes('validation'); + + if (!isRateLimit && !isTimeout && !isValidationError) { + const errBg = `#${sanitizeHexColor(params.bg, '0d1117')}`; + const errAccentRaw = Array.isArray(params.accent) + ? params.accent[params.accent.length - 1] + : params.accent; + const errAccent = `#${sanitizeHexColor(errAccentRaw, '58a6ff')}`; + const errText = `#${sanitizeHexColor(params.text, 'c9d1d9')}`; + const errRadius = sanitizeRadius(params.radius, 8); + + const svg = generateNotFoundSVG( + 'User not found or private account', + errBg, + errAccent, + errText, + errRadius, + params.speed + ); + return new NextResponse(svg, { + status: 200, + headers: { + 'Content-Type': 'image/svg+xml; charset=utf-8', + 'Cache-Control': 'no-cache', + 'Content-Security-Policy': SVG_CSP_HEADER, + }, + }); + } + throw error; } finally { clearTimeout(timeoutId); } diff --git a/app/generator/components/SectionCard.error-resilience.test.tsx b/app/generator/components/SectionCard.error-resilience.test.tsx index bc25c452f..fb5311439 100644 --- a/app/generator/components/SectionCard.error-resilience.test.tsx +++ b/app/generator/components/SectionCard.error-resilience.test.tsx @@ -117,10 +117,10 @@ describe('SectionCard Error Resilience', () => { ); expect(telemetrySpy).toHaveBeenCalledTimes(1); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const [errorArg] = telemetrySpy.mock.calls[0]; expect(errorArg).toBeInstanceOf(Error); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + expect((errorArg as Error).message).toBe('Standard runtime exception'); consoleErrorSpy.mockRestore();