From 3867b6b2965dbc50380f1e9ec6bde53872d05f52 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 5 May 2026 22:20:10 +0000 Subject: [PATCH] fix(api): return 503 for missing fmp config --- backend/src/services/apiServer.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/backend/src/services/apiServer.ts b/backend/src/services/apiServer.ts index 7b12ba8..61433d6 100644 --- a/backend/src/services/apiServer.ts +++ b/backend/src/services/apiServer.ts @@ -133,12 +133,19 @@ const normalizeNewsSymbolsQuery = (value: unknown): string => { const getConfiguredFmpApiKey = (): string => { const apiKey = config.FMP_API_KEY.trim(); if (!apiKey || apiKey.toLowerCase() === 'demo') { - throw new Error('FMP_API_KEY is required for research and screener endpoints'); + throw new MissingServiceConfigError('FMP_API_KEY is required for research and screener endpoints'); } return apiKey; }; +class MissingServiceConfigError extends Error { + constructor(message: string) { + super(message); + this.name = 'MissingServiceConfigError'; + } +} + interface TradeAuditEvent { event: string; userId?: string; @@ -2819,6 +2826,9 @@ RULES: const data = await fetchFmpJson(url) as any; res.json(Array.isArray(data) ? data[0] ?? {} : data); } catch (error: any) { + if (error instanceof MissingServiceConfigError) { + return res.status(503).json({ error: error.message }); + } if (error instanceof FmpFetchError) { return res.status(error.status).json({ error: 'FMP profile fetch failed' }); } @@ -2836,6 +2846,9 @@ RULES: const data = await fetchFmpJson(url) as any; res.json(Array.isArray(data) ? data[0] ?? {} : data); } catch (error: any) { + if (error instanceof MissingServiceConfigError) { + return res.status(503).json({ error: error.message }); + } if (error instanceof FmpFetchError) { return res.status(error.status).json({ error: 'FMP metrics fetch failed' }); } @@ -2853,6 +2866,9 @@ RULES: const data = await fetchFmpJson(url) as any; res.json({ earnings: Array.isArray(data) ? data : [] }); } catch (error: any) { + if (error instanceof MissingServiceConfigError) { + return res.status(503).json({ error: error.message }); + } if (error instanceof FmpFetchError) { return res.status(error.status).json({ error: 'FMP earnings fetch failed' }); } @@ -2883,6 +2899,9 @@ RULES: const data = await fetchFmpJson(url) as any; res.json({ results: Array.isArray(data) ? data : [] }); } catch (error: any) { + if (error instanceof MissingServiceConfigError) { + return res.status(503).json({ error: error.message }); + } if (error instanceof FmpFetchError) { return res.status(error.status).json({ error: 'FMP screener fetch failed' }); }