Advanced
API error fallback
When the ledger returns 500, the UI shows a stable error surface without crashing the route.
User story
As a quality engineer, I want the UI to degrade gracefully on 500 responses so users never see a blank page.
Acceptance criteria
- 500 response renders an error region
- App shell + nav remain visible
- Retry button refetches the route
- Error boundary does not bubble
Manual test steps
- 1.Set up route to return 500
- 2.Open /wallet
- 3.Assert error surface
Expected result
Error region reads 'Wallet service unavailable' and a Retry CTA is present.
Possible bug risks
- Whole app crashes via uncaught error
- Retry CTA loops forever without backoff
- Logs leak the entire error stack to the user
Reference Playwright spec
api-error-fallback.spec.ts
ts1234567891011
import { test, expect } from '@playwright/test';
test('500 surfaces stable error region @regression', async ({ page }) => {
await page.route('**/api/ledger/balance', (route) => {
route.fulfill({ status: 500, body: JSON.stringify({ error: 'ledger_timeout' }) });
});
await page.goto('https://lab.hakdogan.com/wallet');
await expect(page.getByText(/wallet service unavailable/i)).toBeVisible();
await expect(page.getByRole('button', { name: /retry/i })).toBeVisible();
});