Pinecone API Error? Fix “404 Index Not Found”, Connection Timeouts & Dimension Mismatch
Seeing “404 Index not found,” a PineconeConnectionError, or “Vector dimension does not match the dimension of the index”? Here is exactly what causes each Pinecone error and how to fix it — including the environment parameter migration bug that breaks working code after an SDK upgrade.
Fix 1 — “404 Index Not Found”
Stop hardcoding index names and hosts
A 404 on an index you know exists is almost always one of three things: a name typo or wrong casing (Pinecone index names allow only lowercase letters, numbers, and hyphens — no underscores or uppercase), an API key scoped to a different project than the one that owns the index, or a leftover pod-based environment string being used against what is actually a serverless index.
from pinecone import Pinecone
pc = Pinecone(api_key="YOUR_API_KEY")
# Don't guess names or hosts — list what this key can actually see
for idx in pc.list_indexes():
print(idx.name, idx.host)
# Always resolve the host dynamically instead of hardcoding it
desc = pc.describe_index("my-index")
print(desc.host) # e.g. my-index-abc123.svc.us-east-1-aws.pinecone.io
print(desc.dimension) # confirm this matches your embedding model
index = pc.Index(host=desc.host) ServerlessSpec(cloud="aws", region="us-east-1")) and have no environment value at all. Pod-based (legacy) indexes use an environment string like us-west1-gcp. Mixing the two patterns is the single most common cause of a 404 that “should” work.
Fix 2 — PineconeConnectionError & Timeouts
Retry with backoff, then move bulk work to the gRPC client
Connection resets and timeouts are usually a corporate firewall or VPC egress rule blocking HTTPS to *.pinecone.io and the per-index host, a client timeout too short for a large batch upsert, or a genuine data-plane incident. Check live status first, then make every call resilient:
import time
from pinecone.exceptions import PineconeApiException
def upsert_with_retry(index, vectors, max_attempts=5):
for attempt in range(1, max_attempts + 1):
try:
return index.upsert(vectors=vectors)
except (PineconeApiException, TimeoutError, ConnectionError) as e:
if attempt == max_attempts:
raise
wait = min(2 ** attempt, 30)
print(f"Upsert failed ({e}), retrying in {wait}s...")
time.sleep(wait) # For high-throughput upserts or queries, switch to the gRPC
# client — it pools connections and retries transient failures
# far more reliably than the REST client under sustained load
from pinecone.grpc import PineconeGRPC as Pinecone
pc = Pinecone(api_key="YOUR_API_KEY")
index = pc.Index(host=pc.describe_index("my-index").host)
index.upsert(vectors=vectors, batch_size=100) Fix 3 — API Key vs Environment (SDK Migration Bug)
The environment parameter was removed in v3+
The Python package was renamed from pinecone-client to pinecone, and the client no longer takes an environment argument. Upgrading the package without touching the code is the single most common migration break reported against Pinecone:
TypeError: __init__() got an unexpected keyword argument 'environment'
# BEFORE — pinecone-client v1/v2 (removed)
import pinecone
pinecone.init(api_key="YOUR_API_KEY", environment="us-west1-gcp")
index = pinecone.Index("my-index")
# AFTER — pinecone v3+ (pip install pinecone --upgrade)
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key="YOUR_API_KEY") # no environment argument
pc.create_index(
name="my-index",
dimension=1536,
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1"), # region moved here
)
index = pc.Index(host=pc.describe_index("my-index").host) The JS/TS client went through the same migration:
// BEFORE — older @pinecone-database/pinecone client
import { PineconeClient } from '@pinecone-database/pinecone';
const client = new PineconeClient();
await client.init({ apiKey: process.env.PINECONE_API_KEY!, environment: 'us-west1-gcp' });
// AFTER — current client (no environment)
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: process.env.PINECONE_API_KEY! });
const index = pc.index('my-index'); Fix 4 — Dimension Mismatch on Upsert
“Vector dimension does not match the dimension of the index”
Every index has a fixed dimension set at creation. Upserting a vector of any other length fails — most often after swapping embedding models (OpenAI text-embedding-3-small and ada-002 are 1536-dim, text-embedding-3-large is 3072-dim by default).
"message":"Vector dimension 768 does not match the dimension of the index 1536"
embedding = embed_model.encode("some text")
index_info = pc.describe_index("my-index")
if len(embedding) != index_info.dimension:
raise ValueError(
f"Embedding is {len(embedding)}-dim but index expects "
f"{index_info.dimension}-dim. Recreate the index or change models."
)
index.upsert(vectors=[("id1", embedding, {"text": "some text"})]) You cannot change an index’s dimension after creation — delete it with pc.delete_index("my-index") and recreate it with the correct value.
Fix 5 — Rate Limits on the Starter Plan
429s on the free tier — control plane vs data plane
The free Starter plan caps both monthly read/write units and request rate — cross either and Pinecone returns 429 until the window resets. Check current quotas at app.pinecone.io, since they change by plan. One frequent self-inflicted cause: polling describe_index() in a tight loop while waiting for a new index to become ready — control-plane operations (create/list/describe/configure) are throttled far more aggressively than data-plane operations (query/upsert).
import time
from pinecone.exceptions import PineconeApiException
def query_with_backoff(index, vector, top_k=5, max_attempts=6):
for attempt in range(max_attempts):
try:
return index.query(vector=vector, top_k=top_k)
except PineconeApiException as e:
if e.status != 429 or attempt == max_attempts - 1:
raise
time.sleep(min(2 ** attempt, 20))
# Waiting for a new index: sleep between polls, don't hammer describe_index
while not pc.describe_index("my-index").status["ready"]:
time.sleep(2) Fix 6 — Namespaces, Batch Limits & Metadata Filters
Namespace not found vs empty namespace
Pinecone namespaces are not created explicitly — they are just a string tag that appears the moment you first upsert to it. There is no “namespace not found” error: querying a typo’d namespace and querying a correct-but-empty one both return zero matches, silently. Always confirm which namespaces actually hold data:
stats = index.describe_index_stats()
print(stats.namespaces)
# {'': {'vector_count': 0}, 'prod': {'vector_count': 18234}}
# A namespace name that was never upserted to just won't appear here Batch upsert size limits
There is no fixed “vectors per request” number — the real ceiling is a roughly 2MB request payload. That works out to about 1,000–2,000 vectors per batch depending on dimension and how much metadata rides along with each one. Chunk large upserts instead of sending everything at once:
def chunks(seq, size):
for i in range(0, len(seq), size):
yield seq[i:i + size]
# 100-vector batches stay well under the payload ceiling even
# at 3072 dimensions with metadata attached
for batch in chunks(all_vectors, 100):
index.upsert(vectors=batch) Metadata filter syntax errors
Filters use MongoDB-style operators ($eq, $in, $gte, $and, $or). The two most common mistakes: passing a single value where a list is required, and assuming multiple top-level keys mean OR when they actually mean AND.
# WRONG — $in needs a list; two top-level keys = implicit AND, not OR
index.query(vector=embedding, filter={"genre": {"$in": "comedy"}})
# CORRECT
index.query(
vector=embedding,
top_k=5,
filter={
"$or": [
{"genre": {"$in": ["comedy", "drama"]}},
{"year": {"$gte": 2020}},
]
},
) Serverless indexes index every metadata field automatically. On legacy pod-based indexes, a field must be listed in metadata_config at creation or filtering on it silently returns nothing — no error, just an empty result set.
Get an email the next time Pinecone goes down
Outage alerts for Pinecone, straight to your inbox. No account needed, unsubscribe in every email.
Watching more than one service? A free account covers 5 services + a daily digest — and Pro is currently free.
FAQ
What causes Pinecone “404 Index not found”?
Almost always a name typo or wrong casing, an API key scoped to a different project than the one that owns the index, or a leftover pod-based environment host used against a serverless index. Call pc.list_indexes() to see what your key can actually see, and resolve the host from describe_index() instead of hardcoding it.
What causes PineconeConnectionError or timeout issues?
Usually a firewall or VPC egress rule blocking HTTPS to Pinecone’s hosts, a client timeout too short for a large batch upsert, or an active incident. Check prismix.dev/service/pinecone for a live outage, then add retry-with-backoff and switch bulk work to the gRPC client.
Why did my Pinecone code break after upgrading the SDK?
SDK v3 (package renamed pinecone-client → pinecone) removed the environment parameter. Old pinecone.init(environment=...) calls now raise an AttributeError or TypeError. Use Pinecone(api_key=...) and move region onto ServerlessSpec.
How do I fix Pinecone dimension mismatch errors?
The embedding you sent is a different length than the index’s fixed dimension. Compare len(embedding) to pc.describe_index(name).dimension before upserting. Dimension cannot be changed after creation — delete and recreate the index.