# Error Handling

Browser Hybrid provides a custom exception hierarchy.

## Exception Hierarchy

```
BrowserError (base)
├── ConnectionError   # WebSocket connection issues
├── TimeoutError      # Operation timeout
├── TabError          # Tab management errors
└── CDPError          # Chrome DevTools Protocol errors
```

## BrowserError

Base exception for all Browser Hybrid errors.

```python
from browser_hybrid.errors import BrowserError

try:
    browser.navigate("https://example.com")
except BrowserError as e:
    print(f"Browser error: {e}")
```

## ConnectionError

Raised when WebSocket connection fails.

```python
from browser_hybrid.errors import ConnectionError

try:
    browser = Browser()
    browser.navigate("https://example.com")
except ConnectionError as e:
    print(f"Cannot connect to Chrome: {e}")
    print("Make sure Chrome is running with --remote-debugging-port=9222")
```

**Common causes:**
- Chrome not running
- Chrome not started with remote debugging
- Port 9222 in use by another process
- Chrome crashed during operation

## TimeoutError

Raised when an operation exceeds its timeout.

```python
from browser_hybrid.errors import TimeoutError

try:
    browser.wait_for(text="Done", timeout=5.0)
except TimeoutError as e:
    print(f"Timed out waiting: {e}")
```

**Common causes:**
- Page not loading
- Element not appearing
- Network issues
- Wrong selector/text

## TabError

Raised for tab management errors.

```python
from browser_hybrid.errors import TabError

try:
    browser.close_tab(tab)
except TabError as e:
    print(f"Tab error: {e}")
```

**Common causes:**
- Tab already closed
- Invalid tab ID
- Tab not found

## CDPError

Raised for Chrome DevTools Protocol errors.

```python
from browser_hybrid.errors import CDPError

try:
    browser.evaluate("invalid javascript((")
except CDPError as e:
    print(f"CDP error: {e}")
    print(f"Error code: {e.code}")
    print(f"Error message: {e.message}")
```

**Attributes:**
- `code` (int): CDP error code
- `message` (str): Error message

## Error Handling Patterns

### Basic Error Handling

```python
from browser_hybrid import Browser
from browser_hybrid.errors import BrowserError

browser = Browser()
try:
    browser.navigate("https://example.com")
    browser.click_by_text("Submit")
except BrowserError as e:
    print(f"Operation failed: {e}")
finally:
    browser.close()
```

### Specific Error Handling

```python
from browser_hybrid.errors import (
    ConnectionError,
    TimeoutError,
    CDPError,
)

try:
    browser.wait_for(text="Welcome", timeout=10.0)
except ConnectionError:
    print("Lost connection to Chrome")
    # Try to reconnect or exit
except TimeoutError:
    print("Page took too long to load")
    # Retry or handle timeout
except CDPError as e:
    print(f"Chrome error: {e.code} - {e.message}")
    # Handle CDP error
```

### Retry Pattern

```python
import time
from browser_hybrid import Browser
from browser_hybrid.errors import TimeoutError

browser = Browser()

def retry_operation(operation, max_retries=3):
    """Retry an operation on timeout."""
    for attempt in range(max_retries):
        try:
            return operation()
        except TimeoutError:
            if attempt < max_retries - 1:
                time.sleep(1)
                continue
            raise

# Use retry
retry_operation(lambda: browser.wait_for(text="Done", timeout=5.0))
```

### Graceful Degradation

```python
from browser_hybrid import Browser
from browser_hybrid.errors import BrowserError

def safe_click(browser, text):
    """Click with fallback."""
    try:
        browser.click_by_text(text)
        return True
    except BrowserError:
        # Fallback: try by ref
        try:
            tree = browser.accessibility_tree()
            elements = tree.find_by_name(text)
            if elements:
                browser.click(elements[0].ref)
                return True
        except BrowserError:
            pass
    return False
```

## Best Practices

1. **Always close browser in finally**

```python
browser = Browser()
try:
    browser.navigate("https://example.com")
    # ... operations ...
finally:
    browser.close()
```

2. **Use context manager (planned)**

```python
# Future feature
with Browser() as browser:
    browser.navigate("https://example.com")
# Auto-closes
```

3. **Handle specific errors**

```python
# Good: Specific handling
try:
    browser.wait_for(text="Done")
except TimeoutError:
    print("Timeout")
except ConnectionError:
    print("Disconnected")

# Avoid: Catching all exceptions
try:
    browser.wait_for(text="Done")
except Exception:
    pass  # Bad: Silently ignores all errors
```

4. **Log errors with context**

```python
try:
    result = browser.evaluate("someFunction()")
except CDPError as e:
    logger.error(f"Failed to evaluate script: {e}")
    logger.debug(f"Script was: someFunction()")
    raise
```