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 ? (
-
Updates on things we're working on right now