Handling Errors and Retries
1. Understanding Pinecone Error Types
| Error | HTTP | Meaning |
|---|---|---|
| PineconeApiException | varies | General API error |
| NotFoundException | 404 | Index/namespace missing |
| UnauthorizedException | 401 | Bad API key |
| ForbiddenException | 403 | No permission |
| PineconeApiAttributeError | ā | SDK misuse |
| ServiceException | 5xx | Server-side |
2. Implementing Exponential Backoff
Example: Backoff Wrapper
import time, random
def with_backoff(fn, *args, max_tries=5, **kw):
for i in range(max_tries):
try:
return fn(*args, **kw)
except Exception as e:
if i == max_tries - 1: raise
wait = (2 ** i) + random.random()
time.sleep(wait)
3. Handling Rate Limits
Example: 429 Handler
from pinecone.exceptions import PineconeApiException
try:
index.upsert(vectors=batch)
except PineconeApiException as e:
if e.status == 429:
time.sleep(int(e.headers.get("Retry-After", "5")))
index.upsert(vectors=batch)
else: raise
4. Implementing Retry Logic
Example: Tenacity
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(5),
wait=wait_exponential(min=1, max=30))
def safe_query(qv):
return index.query(vector=qv, top_k=10)
5. Handling Network Errors
| Error | Action |
|---|---|
| ConnectionError | Retry with backoff |
| Timeout | Retry; check region/proxy |
| DNS | Verify endpoint host |
6. Handling Timeout Errors
Example: Custom Timeout
from pinecone import Pinecone
pc = Pinecone(api_key="...", additional_headers={"x-request-timeout": "30"})
7. Implementing Circuit Breakers
Example: pybreaker
import pybreaker
breaker = pybreaker.CircuitBreaker(fail_max=5, reset_timeout=30)
@breaker
def query(qv):
return index.query(vector=qv, top_k=10)
8. Handling Partial Failures
Example: Per-Batch Failure
failed = []
for b in batches:
try: index.upsert(vectors=b)
except Exception: failed.append(b)
# retry failed later
for b in failed: with_backoff(index.upsert, vectors=b)
9. Logging Error Details
Example: Structured Error Log
try:
index.query(vector=qv, top_k=10)
except PineconeApiException as e:
log.error("pinecone_query_failed", extra={
"status": e.status,
"reason": e.reason,
"body": getattr(e, "body", None),
})
raise
10. Implementing Idempotent Operations
Note: Upserts are naturally idempotent by ID ā re-running the same upsert produces the same result. Use stable, deterministic IDs.
11. Recovering from Failed Upserts
| Strategy | Detail |
|---|---|
| Persist failed IDs | To dead-letter queue |
| Replay later | Backoff job |
| Verify with fetch | Confirm presence |