# Error Handling

Handle errors gracefully in your Pinecone applications.

## Exception Hierarchy

All Pinecone exceptions inherit from `PineconeError`:

```
PineconeError
├── ConfigurationError
│   ├── InvalidAPIKeyError
│   └── InvalidConfigError
├── APIConnectionError
│   ├── TimeoutError
│   └── ConnectionError
└── APIError
    ├── BadRequestError
    ├── UnauthorizedError
    ├── ForbiddenError
    ├── NotFoundError
    ├── RateLimitError
    └── ServerError
```

## Basic Error Handling

Catch all Pinecone errors:

```python
from pinecone import Pinecone, PineconeError

pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except PineconeError as e:
    print(f"Pinecone error: {e}")
```

## Handling Specific Errors

### Authentication Errors

Handle invalid API keys:

```python
from pinecone import Pinecone, UnauthorizedError

try:
    pc = Pinecone(api_key="invalid-key")
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except UnauthorizedError:
    print("Invalid API key. Please check your credentials.")
```

### Rate Limiting

Handle rate limit errors with retry logic:

```python
import time
from pinecone import Pinecone, RateLimitError

pc = Pinecone(api_key="your-api-key")

max_retries = 3
retry_delay = 1.0

for attempt in range(max_retries):
    try:
        response = pc.inference.embed(
            model="multilingual-e5-large",
            texts=["Hello world"]
        )
        break
    except RateLimitError as e:
        if attempt == max_retries - 1:
            raise
        print(f"Rate limited, retrying in {retry_delay}s...")
        time.sleep(retry_delay)
        retry_delay *= 2  # Exponential backoff
```

### Connection Errors

Handle network failures:

```python
from pinecone import Pinecone, APIConnectionError, TimeoutError

pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except TimeoutError:
    print("Request timed out. Check your network connection.")
except APIConnectionError as e:
    print(f"Connection failed: {e}")
```

### Validation Errors

Handle invalid requests:

```python
from pinecone import Pinecone, BadRequestError

pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="invalid-model",
        texts=[]  # Empty texts list
    )
except BadRequestError as e:
    print(f"Invalid request: {e}")
```

## Error Information

Exceptions include useful information:

```python
from pinecone import Pinecone, APIError

pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except APIError as e:
    print(f"Error message: {e.message}")
    print(f"Status code: {e.status_code}")
    print(f"Response body: {e.response_body}")
```

### Accessing Request Metadata

All API errors include additional metadata for debugging:

```python
from pinecone import Pinecone, APIError

pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except APIError as e:
    # Basic information
    print(f"Error: {e.message}")
    print(f"Status: {e.status_code}")
    
    # Request metadata (available when provided by server)
    if e.request_id:
        print(f"Request ID: {e.request_id}")
    
    if e.error_code:
        print(f"Error code: {e.error_code}")
    
    if e.url:
        print(f"URL: {e.url}")
    
    if e.method:
        print(f"Method: {e.method}")
```

### Using Request ID for Support

Include the request ID when contacting support:

```python
import logging
from pinecone import Pinecone, APIError

logger = logging.getLogger(__name__)
pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except APIError as e:
    # Log all available context
    logger.error(
        f"API request failed: {e.message}",
        extra={
            "request_id": e.request_id,
            "error_code": e.error_code,
            "status_code": e.status_code,
            "url": e.url,
            "method": e.method,
        }
    )
    
    # Display request ID to user for support
    if e.request_id:
        print(f"Error occurred. Reference request ID {e.request_id} when contacting support.")
    
    raise
```

### Handling Specific Error Codes

Use error codes for programmatic error handling:

```python
from pinecone import Pinecone, BadRequestError

pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except BadRequestError as e:
    # Handle specific error codes
    if e.error_code == "INVALID_MODEL":
        print("Model not found. Use a supported model.")
    elif e.error_code == "INVALID_INPUT":
        print("Input text is invalid. Check format and encoding.")
    else:
        print(f"Bad request: {e.message}")
```

## Best Practices

### Catch Specific Exceptions First

Order exception handlers from specific to general:

```python
from pinecone import (
    Pinecone,
    UnauthorizedError,
    RateLimitError,
    APIError,
    PineconeError
)

pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except UnauthorizedError:
    print("Authentication failed")
except RateLimitError:
    print("Rate limit exceeded")
except APIError as e:
    print(f"API error: {e}")
except PineconeError as e:
    print(f"Unexpected error: {e}")
```

### Async Error Handling

Handle errors in async code:

```python
import asyncio
from pinecone import AsyncPinecone, PineconeError

async def main():
    async with AsyncPinecone(api_key="your-api-key") as pc:
        try:
            response = await pc.inference.embed(
                model="multilingual-e5-large",
                texts=["Hello world"]
            )
        except PineconeError as e:
            print(f"Error: {e}")

asyncio.run(main())
```

### Logging Errors

Log errors for debugging:

```python
import logging
from pinecone import Pinecone, PineconeError

logger = logging.getLogger(__name__)

pc = Pinecone(api_key="your-api-key")

try:
    response = pc.inference.embed(
        model="multilingual-e5-large",
        texts=["Hello world"]
    )
except PineconeError as e:
    logger.error("Pinecone operation failed", exc_info=True)
    raise
```

### Validation Before API Calls

Validate inputs before making API calls:

```python
from pinecone import Pinecone

pc = Pinecone(api_key="your-api-key")

texts = ["Hello world"]

if not texts:
    raise ValueError("texts cannot be empty")

response = pc.inference.embed(
    model="multilingual-e5-large",
    texts=texts
)
```

## Next Steps

- Review the [exceptions reference](../api/exceptions.rst)
- Learn about [configuration](configuration.md)
- Explore the [API reference](../api/client.rst)
