# Network errors show a retry option rather than silently failing

- **Pattern:** `ab-000149` (`ai-chat-visibility.error-handling.network-error-recovery`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000149
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000149)

## Why it matters

Network errors mid-stream — Wi-Fi dropouts, CDN hiccups, tunnel reconnects on mobile — will freeze the UI with `isLoading` stuck true if the error handler only catches HTTP-status errors and ignores `TypeError: Failed to fetch`. The user sees an animated typing indicator spinning forever with no recovery path short of a hard refresh, which also loses the partial response they had already generated. This is a routine failure mode on mobile networks and must be handled distinctly from API errors.

## Severity rationale

High because a stuck UI with no retry path is indistinguishable from a broken product and happens routinely on mobile.

## Remediation

In your chat hook at `src/hooks/useChat.ts`, branch explicitly on network-level errors (`TypeError` with a fetch-related message), always reset `isLoading` in the catch block, preserve any partial response already streamed, and attach a `window.addEventListener('online', ...)` to offer automatic recovery when connectivity returns.

```ts
catch (err) {
  if (err instanceof TypeError && err.message.includes('fetch')) {
    setError('Connection lost. Check your internet connection and try again.');
  }
  setIsLoading(false);
}
```

## Detection

- **ID:** `network-error-recovery`
- **Severity:** `high`
- **What to look for:** Count all error handler branches that distinguish network-level failures from API errors. Check specifically for handling of: `TypeError: Failed to fetch`, AbortError from timeouts, and offline/connection-lost scenarios. These are distinct from API errors that return HTTP responses. Look for `navigator.onLine` checks, offline event listeners, or specific TypeError handling in the chat error handler. When a network error occurs mid-stream, the partial response should be preserved and a retry option shown.
- **Pass criteria:** Network errors (failed fetch, offline, timeout) are caught and display a retry option. The partial response content (if any) is preserved in view. The user is not left with a frozen interface. At least 1 network-specific error branch must exist.
- **Fail criteria:** Network errors cause the UI to freeze or silently fail with `isLoading` stuck as true. The chat appears broken with no recovery path.
- **Skip (N/A) when:** No AI chat interface detected. Signal: same as `response-streaming-progressive`.
- **Detail on fail:** `"Network errors (TypeError: Failed to fetch) not specifically handled — chat UI freezes with isLoading stuck as true on connection loss"`
- **Remediation:** In your chat hook at `src/hooks/useChat.ts` or error handler, distinguish network errors:

  ```ts
  catch (err) {
    if (err instanceof TypeError && err.message.includes('fetch')) {
      setError('Connection lost. Check your internet connection and try again.');
    }
    setIsLoading(false); // Always reset loading state
  }
  ```

  Add a `window.addEventListener('online', ...)` listener to automatically restore the UI when connectivity returns.

---

Taxons: error-resilience, user-experience

HTML version: https://auditbuffet.com/patterns/ab-000149
