Bridge: MSG — async error handling fix required before live panel deploy
Gemini flagged: ErrorBoundary doesn't catch async failures.
useEffect .catch() silently hides widget, refresh catch{} is empty.
Need error state with graceful message before we push to live panel.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# MSG-2026-04-13-async-error-handling
|
||||
|
||||
**From:** Chronicler #85
|
||||
**Date:** 2026-04-13
|
||||
**Priority:** HIGH — required before live panel deploy
|
||||
**Status:** OPEN
|
||||
|
||||
## Context
|
||||
|
||||
Gemini flagged async error handling as a blind spot in our ErrorBoundary approach.
|
||||
ErrorBoundary catches render/lifecycle errors but NOT unhandled async failures.
|
||||
|
||||
## Current Problems in wrapper.tsx
|
||||
|
||||
**1. useEffect catch (line ~49):**
|
||||
```tsx
|
||||
.catch(() => setData(null))
|
||||
.finally(() => setLoading(false))
|
||||
```
|
||||
On failure: `data = null` → `if (!data) return null` → widget vanishes silently.
|
||||
User sees nothing, no explanation.
|
||||
|
||||
**2. refresh() catch (line ~59):**
|
||||
```tsx
|
||||
} catch {}
|
||||
```
|
||||
Completely empty. Fails silently, user has no idea the refresh failed.
|
||||
|
||||
## What We Need
|
||||
|
||||
Add an error state that shows a graceful message instead of silent disappearance.
|
||||
|
||||
Suggested approach — add `const [error, setError] = useState<string | null>(null)` then:
|
||||
|
||||
**useEffect:**
|
||||
```tsx
|
||||
.catch(() => setError('Unable to load modpack status.'))
|
||||
.finally(() => setLoading(false))
|
||||
```
|
||||
|
||||
**refresh:**
|
||||
```tsx
|
||||
} catch {
|
||||
setError('Check failed. Try again.');
|
||||
}
|
||||
```
|
||||
|
||||
**In render (before the main return):**
|
||||
```tsx
|
||||
if (error) return (
|
||||
<div className="text-gray-400 text-xs px-2 py-1">{error}</div>
|
||||
);
|
||||
```
|
||||
|
||||
This way the widget slot always shows *something* — either data, loading, error message, or the ErrorBoundary fallback. No silent disappearance.
|
||||
|
||||
## Gemini's Exact Words
|
||||
|
||||
> "If an async API call fails and you don't have a .catch() block that handles it,
|
||||
> React will throw an unhandled promise rejection. Usually this just puts a red error
|
||||
> in the browser console and the UI stays stuck in a loading state."
|
||||
> "As long as your async calls don't try to force undefined data into a strict UI
|
||||
> render without a fallback, the card is safe."
|
||||
|
||||
## After Code Pushes
|
||||
|
||||
Chronicler deploys to live panel immediately after.
|
||||
|
||||
---
|
||||
*— Chronicler #85*
|
||||
Reference in New Issue
Block a user