# Error Handling All exceptions raised by the SDK are subclasses of `PineconeError`, so a single `except PineconeError` block catches everything the SDK can raise. More specific subclasses let you handle individual failure modes differently. ## Exception Hierarchy ``` PineconeError (base) ├── ApiError # Server returned an HTTP error response │ ├── NotFoundError # 404 │ ├── ConflictError # 409 │ ├── UnauthorizedError # 401 │ ├── ForbiddenError # 403 │ ├── PaymentRequiredError # 402 │ ├── FailedPreconditionError # 412 │ ├── RateLimitError # 429 │ └── ServiceError # 5xx ├── PineconeConnectionError # Network-level failure (DNS, refused, transport) ├── PineconeTimeoutError # Operation exceeded its timeout ├── PineconeValueError # Invalid value passed to the SDK └── PineconeTypeError # Wrong type passed to the SDK ``` Full reference: {doc}`/reference/exceptions`. ## Catching Specific Errors ```python from pinecone import Pinecone from pinecone.errors import ( NotFoundError, ConflictError, UnauthorizedError, ForbiddenError, PaymentRequiredError, FailedPreconditionError, RateLimitError, ServiceError, PineconeConnectionError, PineconeTimeoutError, ) pc = Pinecone() try: pc.indexes.delete("nonexistent-index") except NotFoundError: print("Index does not exist") except ConflictError: print("Operation conflicts with current state") except UnauthorizedError: print("Invalid or missing API key") except ForbiddenError: print("API key lacks permission for this operation") except PaymentRequiredError as exc: print(f"Billing blocks this operation: {exc.message}") except FailedPreconditionError as exc: print(f"Resource is not in a state that permits this: {exc.message}") except RateLimitError: print("Rate limited; backing off before retrying") except ServiceError as exc: print(f"Server error {exc.status_code}: {exc.message}") except PineconeConnectionError: print("Network error; check your connection") except PineconeTimeoutError: print("Request timed out") ``` ## ApiError Attributes `ApiError` (and its subclasses) carry structured context: | Attribute | Type | Description | |-----------|------|-------------| | `status_code` | `int` | HTTP status code returned by the server | | `message` | `str` | Human-readable error description | | `body` | `dict \| None` | Parsed response body, if available | | `reason` | `str \| None` | HTTP reason phrase | | `headers` | `dict \| None` | Response headers | | `error_code` | `str \| None` | Server-provided error code, if present | | `request_id` | `str \| None` | Request ID for correlating with support, if present | ```python from pinecone.errors import ApiError try: pc.indexes.describe("my-index") except ApiError as exc: print(exc.status_code) # e.g. 404 print(exc.message) if exc.body: print(exc.body.get("error", {}).get("message")) ``` ## ConflictError when creating an index If you call `pc.indexes.create()` and an index with that name already exists, the server returns a 409 and the SDK raises `ConflictError`. The idiomatic fix is to guard the create call with `pc.indexes.exists()`: ```python from pinecone import Pinecone pc = Pinecone() if not pc.indexes.exists("my-index"): pc.indexes.create( name="my-index", schema={"fields": {"embedding": {"type": "dense_vector", "dimension": 1536, "metric": "cosine"}}}, deployment={"deployment_type": "managed", "cloud": "aws", "region": "us-east-1"}, ) ``` `exists()` returns `True` if an index with that name is present, `False` otherwise. If you genuinely cannot check first (e.g. concurrent callers), catch `ConflictError` and treat it as a no-op: ```python from pinecone import Pinecone from pinecone.errors import ConflictError pc = Pinecone() try: pc.indexes.create( name="my-index", schema={"fields": {"embedding": {"type": "dense_vector", "dimension": 1536, "metric": "cosine"}}}, deployment={"deployment_type": "managed", "cloud": "aws", "region": "us-east-1"}, ) except ConflictError: pass # index already exists, nothing to do ``` ## Retries The SDK retries failed requests automatically with decorrelated jitter on the backoff path, and bulk operations self-tune effective concurrency in response to throttling. Full retry behavior, configuration, and multi-process guidance: {doc}`/guides/retries`. ## Timeouts The default request timeout is **30 seconds**. Pass `timeout` to the `Pinecone` constructor to change the client-wide default: ```python pc = Pinecone(timeout=10.0) ``` Many methods also accept a per-request `timeout` keyword argument that overrides the client default for that call: ```python # Wait up to 60 seconds for this specific upsert index.upsert(vectors=[...], timeout=60.0) ``` When a request times out, the SDK raises `PineconeTimeoutError`, which also inherits from Python's built-in `TimeoutError`: ```python except TimeoutError: # Catches PineconeTimeoutError as well ... ```