--- title: Error Handling Pattern category: patterns --- # Error Handling Pattern ## Rules - Use explicit exceptions for domain/error classification (e.g., ProviderError, ValueError). - Prefer logging.exception when catching an exception where stack trace is useful. - Avoid broad except: clauses that swallow exceptions; if broad except is used for "best-effort" fallback, log at warning and include original exception context. - For public library-like functions, prefer raising typed exceptions instead of returning magic values ([], False) — only return safe defaults where documented. ## Examples ### ai_provider.py - Network error to ProviderError ```python except requests.ConnectionError as exc: if attempt == retries: raise ProviderError( f"Connection error when calling provider: {exc}" ) from exc ... ``` ### pipeline/ai_provider_wrapper.py - Best-effort with logging ```python except Exception: _logger.exception("Failed to append audit event for embedding failure") results[j] = None ``` ### similarity/compute.py - Defensive import handling ```python try: import duckdb except Exception: logger.exception("duckdb import failed; cannot load vectors") return 0 ``` ## Anti-Patterns ### Bad: Silent exception swallowing ```python try: do_work() except Exception: return [] # BAD: hides the root cause and returns an ambiguous default ``` **Remediation**: Narrow exception types or at minimum log.exception() and re-raise or convert to a domain error if truly handled. ### Bad: Mixing print() and logging **Problem**: Mixing print() and logging for errors. **Remediation**: Replace print() calls with logger.* calls; use structured logging configuration.