supabase/supabase · error · ResponseError
Failed to fetch incident status: ${response.statusText}
Error message
Failed to fetch incident status: ${response.statusText} What it means
Thrown by getIncidentStatus as a ResponseError when the fetch to the incident-status endpoint returns non-2xx. Unlike the banner error, this carries structured data: response.status and an optional retryAfter parsed from the Retry-After response header (only when it is a finite positive number). The function also logs the status and body text to console.error before throwing.
Source
Thrown at apps/studio/data/platform/incident-status-query.ts:32
method: 'GET',
credentials: 'omit',
headers: {
'Content-Type': 'application/json',
},
})
if (!response.ok) {
const errorText = await response.text()
console.error('[getIncidentStatus] Failed:', response.status, errorText)
let retryAfter: number | undefined
const retryAfterHeader = response.headers.get('Retry-After')
if (retryAfterHeader !== null) {
const parsed = Number(retryAfterHeader)
if (Number.isFinite(parsed) && parsed > 0) retryAfter = parsed
}
throw new ResponseError(
`Failed to fetch incident status: ${response.statusText}`,
response.status,
undefined,
retryAfter
)
}
const data = await response.json()
const [maintenanceEvents, incidents] = partition(
data ?? [],
(event) => event.impact === 'maintenance'
)
return { maintenanceEvents, incidents }
}
export type IncidentStatusData = Awaited<ReturnType<typeof getIncidentStatus>>
export type IncidentStatusError = unknown
View on GitHub (pinned to beee91b9c2)
Solutions
- Inspect err.status and honor err.retryAfter before retrying the query.
- Surface a degraded status state in the UI rather than crashing.
- Check the upstream status provider and Studio API health.
- For 429s, configure the query's retryDelay to respect the Retry-After value.
Example fix
// before: generic catch
try { await getIncidentStatus() } catch (e) { /* ? */ }
// after: structured handling
try {
const status = await getIncidentStatus()
} catch (e) {
if (e instanceof ResponseError && e.status === 429 && e.retryAfter) {
scheduleRetryIn(e.retryAfter)
} else {
showDegradedStatus()
}
} Defensive patterns
Strategy: try-catch
Type guard
const isIncidentStatusResponseError = (e: unknown): e is ResponseError => e instanceof ResponseError && /Failed to fetch incident status/.test(e.message) // 429 with Retry-After const isRateLimited = (e: ResponseError): boolean => e.status === 429 && typeof e.retryAfter === 'number' && e.retryAfter > 0
Try / catch
try {
const status = await getIncidentStatus(signal)
// render status
} catch (e) {
if (e instanceof ResponseError) {
if (e.status === 429 && typeof e.retryAfter === 'number') {
// honor Retry-After before next query attempt
await delay(e.retryAfter * 1000)
} else if (e.status >= 500) {
showDegradedStatus()
} else {
// 4xx other than 429: surface to UI
showStatusError(e)
}
return
}
throw e
} Prevention
- Honor err.retryAfter (seconds) before retrying on 429 responses.
- Surface a degraded status state in the UI for 5xx instead of crashing.
- Check the upstream status provider and Studio API health when errors persist.
- The function already console.errors status + body text; inspect server logs for diagnosis.
When it happens
Trigger: The incident-status endpoint returns 4xx/5xx. A 429 typically carries a Retry-After header that the function captures and exposes on the error; a 5xx indicates the upstream status provider or Studio API is failing.
Common situations: Status provider rate-limited (429 + Retry-After); upstream status feed down; Studio API route misconfigured; auth/permission issues surfacing as 401/403.
Related errors
- Failed to fetch incident banner: ${response.statusText}
- API v${version} responded with ${response.status}
- body?.message
- Unable to reach the server. Please check your network or try
- Failed to fetch full values for truncated cells
AI-assisted analysis of supabase/supabase@beee91b9c2 (2026-08-12).
Data as JSON: /api/errors/0399df2e2b169547.
Report an issue: GitHub.