From a3bb743b0d033db8623449a335281a61a4b1b374 Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 00:47:48 +0000 Subject: [PATCH] fix: handle non-JSON Squeak API responses in community widgets The Newbies, Anniversaries, and WIP widgets fetched from the Squeak API and piped the response straight into res.json() with no res.ok check and no .catch(). When the upstream returned an HTML error page, res.json() threw an unhandled SyntaxError and loading never flipped to false, leaving the skeleton spinner stuck forever. Now each widget checks res.ok before parsing and catches errors, degrading to an empty list (Newbies, Anniversaries) or rendering nothing (WIP) instead of hanging on the skeleton. Generated-By: PostHog Code Task-Id: 537aa304-78e6-4ffe-8458-cd099ec8f1fb --- .../InsidePostHog/Anniversaries.tsx | 11 ++++++- src/components/InsidePostHog/Newbies.tsx | 11 ++++++- src/components/InsidePostHog/WIP.tsx | 30 ++++++++++++------- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/components/InsidePostHog/Anniversaries.tsx b/src/components/InsidePostHog/Anniversaries.tsx index e65ee814cead..12bbd03a0de5 100644 --- a/src/components/InsidePostHog/Anniversaries.tsx +++ b/src/components/InsidePostHog/Anniversaries.tsx @@ -29,7 +29,12 @@ export default function Anniversaries() { { encodeValuesOnly: true } ) fetch(`${process.env.GATSBY_SQUEAK_API_HOST}/api/profiles?${query}`) - .then((res) => res.json()) + .then((res) => { + if (!res.ok) { + throw new Error(`Failed to fetch profiles: ${res.status}`) + } + return res.json() + }) .then(({ data }) => { const teamMembers = data.filter((teamMember) => { const { @@ -45,6 +50,10 @@ export default function Anniversaries() { setTeamMembers(teamMembers) setLoading(false) }) + .catch(() => { + setTeamMembers([]) + setLoading(false) + }) }, []) return loading ? ( diff --git a/src/components/InsidePostHog/Newbies.tsx b/src/components/InsidePostHog/Newbies.tsx index a4b1676542f1..245b1ac9f644 100644 --- a/src/components/InsidePostHog/Newbies.tsx +++ b/src/components/InsidePostHog/Newbies.tsx @@ -29,11 +29,20 @@ export default function Newbies() { { encodeValuesOnly: true } ) fetch(`${process.env.GATSBY_SQUEAK_API_HOST}/api/profiles?${query}`) - .then((res) => res.json()) + .then((res) => { + if (!res.ok) { + throw new Error(`Failed to fetch profiles: ${res.status}`) + } + return res.json() + }) .then(({ data }) => { setNewbies(data) setLoading(false) }) + .catch(() => { + setNewbies([]) + setLoading(false) + }) }, []) return loading ? ( diff --git a/src/components/InsidePostHog/WIP.tsx b/src/components/InsidePostHog/WIP.tsx index 65ceccf4d64c..0418d1971039 100644 --- a/src/components/InsidePostHog/WIP.tsx +++ b/src/components/InsidePostHog/WIP.tsx @@ -28,7 +28,12 @@ const getRecentUpdate = async () => { }, { encodeValuesOnly: true } )}` - ).then((res) => res.json()) + ).then((res) => { + if (!res.ok) { + throw new Error(`Failed to fetch team updates: ${res.status}`) + } + return res.json() + }) return data } @@ -36,24 +41,27 @@ export default function WIP() { const [recentUpdate, setRecentUpdate] = useState() const [loading, setLoading] = useState(true) useEffect(() => { - getRecentUpdate().then((recentUpdate) => setRecentUpdate(recentUpdate?.[0])) + getRecentUpdate() + .then((recentUpdate) => setRecentUpdate(recentUpdate?.[0])) + .catch(() => setRecentUpdate(undefined)) + .finally(() => setLoading(false)) }, []) - useEffect(() => { - if (recentUpdate) { - setLoading(false) - } - }, [recentUpdate]) - const team = recentUpdate?.attributes?.team?.data?.attributes const profile = recentUpdate?.attributes?.question?.data?.attributes?.profile?.data const name = [profile?.attributes?.firstName, profile?.attributes?.lastName].filter(Boolean).join(' ') const avatarURL = profile?.attributes?.avatar?.data?.attributes?.formats?.thumbnail?.url const roadmap = recentUpdate?.attributes?.roadmap?.data - return loading ? ( - - ) : ( + if (loading) { + return + } + + if (!recentUpdate) { + return null + } + + return (

WIP

Updates on things we're working on right now