Back to Pinecone Python Client

Error Handling

docs/guides/error-handling.md

9.0.04.7 KB
Original Source

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
│   └── 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,
    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 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:

AttributeTypeDescription
status_codeintHTTP status code returned by the server
messagestrHuman-readable error description
bodydict | NoneParsed response body, if available
reasonstr | NoneHTTP reason phrase
headersdict | NoneResponse headers
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",
        spec={"serverless": {"cloud": "aws", "region": "us-east-1"}},
        dimension=1536,
        metric="cosine",
    )

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",
        spec={"serverless": {"cloud": "aws", "region": "us-east-1"}},
        dimension=1536,
        metric="cosine",
    )
except ConflictError:
    pass  # index already exists, nothing to do

Retries

The SDK retries failed requests automatically. The default RetryConfig retries up to 3 attempts total (1 initial + 2 retries) with exponential backoff for status codes 429, 500, 502, 503, and 504.

Customize retry behavior by passing a RetryConfig to Pinecone():

python
from pinecone import Pinecone, RetryConfig

pc = Pinecone(
    retry_config=RetryConfig(
        max_retries=5,
        backoff_factor=1.0,
        max_wait=30.0,
        retryable_status_codes=frozenset({429, 500, 503}),
    )
)

To disable retries entirely, set max_retries=1:

python
pc = Pinecone(retry_config=RetryConfig(max_retries=1))

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
    ...