# Search handles errors with user-facing message, not raw error or empty list

- **Pattern:** `ab-001071` (`directory-search-discovery.pagination-url.error-handling`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001071
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001071)

## Why it matters

A blank page or raw stack trace on a search error tells users nothing actionable and exposes internal implementation details — error messages containing `TypeError: Cannot read property of undefined` or Prisma stack traces reveal your ORM, schema, and query structure. Under ISO 25010:2011 reliability, an application that silently drops into an empty state on network failure or backend error leaves users unable to distinguish "no results" from "broken search" — and they'll assume the latter, blame the product, and leave.

## Severity rationale

Medium because the failure degrades user trust and leaks implementation details without constituting a direct data breach or service outage.

## Remediation

Wrap the search fetch in `try/catch` and render a non-technical error message when the request fails. In `components/SearchInput.tsx`:

```tsx
try {
  const res = await fetch(`/api/listings?q=${encodeURIComponent(query)}`)
  if (!res.ok) throw new Error('non-2xx')
  const data = await res.json()
  setResults(data.listings)
} catch {
  setError('Search is temporarily unavailable. Please try again.')
}

// In render:
{error && (
  <div role="alert" className="bg-red-50 border border-red-200 p-4 rounded">
    {error}
  </div>
)}
```

Log the original error to the server (not to the client). Never render `err.message` directly — it will contain stack traces or ORM internals.

## Detection

- **ID:** `error-handling`
- **Severity:** `medium`
- **What to look for:** Enumerate all relevant files and Intentionally trigger a search error (if possible — e.g., search for a term that causes a backend error, or simulate a network failure in dev tools). Check whether the UI displays a user-friendly error message (e.g., "Search temporarily unavailable. Please try again.") instead of showing nothing, a blank page, or a technical error stack trace.
- **Pass criteria:** At least 1 conforming pattern must exist. Search errors result in a clear, user-friendly error message (not a stack trace or empty list). A suggestion to retry or try different terms may be provided.
- **Fail criteria:** Search errors show a blank page, technical stack trace, or raw error message.
- **Skip (N/A) when:** Search is not implemented or error states are not testable. Signal: no search functionality found.
- **Detail on fail:** `"Search error causes blank page with no error message."` or `"Raw API error shown to user: 'TypeError: Cannot read property of undefined'."`
- **Remediation:** Wrap search API calls in error handling:

  ```tsx
  // components/SearchInput.tsx
  const handleSearch = async (query) => {
    setLoading(true)
    setError(null)
    try {
      const res = await fetch(`/api/listings?q=${encodeURIComponent(query)}`)
      if (!res.ok) throw new Error('Search failed')
      const data = await res.json()
      setResults(data.listings)
    } catch (err) {
      setError('Search is temporarily unavailable. Please try again.')
      console.error('Search error:', err) // log for debugging
    } finally {
      setLoading(false)
    }
  }

  // In render:
  {error && (
    <div className="bg-red-50 border border-red-200 p-4 rounded">
      {error}
    </div>
  )}
  ```

## External references

- iso-25010 reliability

Taxons: error-resilience

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