Skip to content

fix(vector_stores): pass namespace as top-level kwarg to UpstashVector query_many#5202

Merged
kartik-mem0 merged 1 commit into
mem0ai:mainfrom
gaurav0107:fix/4207-upstashvector-search-namespace-bug
Jun 10, 2026
Merged

fix(vector_stores): pass namespace as top-level kwarg to UpstashVector query_many#5202
kartik-mem0 merged 1 commit into
mem0ai:mainfrom
gaurav0107:fix/4207-upstashvector-search-namespace-bug

Conversation

@gaurav0107

Copy link
Copy Markdown
Contributor

Linked Issue

Closes #4207

Description

UpstashVector.search() was passing namespace inside each per-query
dict to upstash_vector.Index.query_many(). The Upstash client expects
namespace as a top-level keyword argument; the QueryRequest
TypedDict has no namespace field, so the per-query value was silently
dropped and every query routed to the default namespace.

When len(queries) == 1, query_many internally calls
self.query(**query, namespace=namespace) — which raises
TypeError: got multiple values for keyword argument 'namespace' because
namespace ends up bound twice.

This PR moves namespace from each query dict onto query_many's
top-level kwarg, matching the Upstash client signature
(upstash_vector.core.index_operations.IndexOperations.query_many,
v0.8.0).

-            queries = [
-                {
-                    "vector": v,
-                    "top_k": top_k,
-                    "filter": filters_str or "",
-                    "include_metadata": True,
-                    "namespace": self.collection_name,
-                }
-                for v in vectors
-            ]
-            responses = self.client.query_many(queries=queries)
+            queries = [
+                {
+                    "vector": v,
+                    "top_k": top_k,
+                    "filter": filters_str or "",
+                    "include_metadata": True,
+                }
+                for v in vectors
+            ]
+            responses = self.client.query_many(queries=queries, namespace=self.collection_name)

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Refactor (no functional changes)
  • Documentation update

Breaking Changes

N/A — this fixes the search path so enable_embeddings=False users
actually receive results from their configured namespace. Users who never
set a custom collection_name saw no visible effect; users who did were
silently returned data from the wrong namespace, or hit a TypeError on
single-query search.

Test Coverage

  • I added/updated unit tests
  • I added/updated integration tests
  • I tested manually (describe below)
  • No tests needed (explain why)

Updated test_search_vectors and test_search_vectors_empty_filters to
assert the new (correct) call shape, and added
test_search_vectors_multi_query_namespace_at_top_level as a regression
test that locks in the fix on the multi-query path. The new test was
verified to fail on the buggy code and pass on the fix.

tests/vector_stores/test_upstash_vector.py ............. 19 passed

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have added tests that prove my fix/feature works
  • New and existing tests pass locally
  • I have updated documentation if needed (not applicable — internal
    bug fix in vector store call shape, no public API change)

…r query_many

The Upstash client's `Index.query_many` takes `namespace` as a top-level
keyword argument, and the per-query `QueryRequest` TypedDict has no
`namespace` field. Passing `"namespace": self.collection_name` inside each
per-query dict caused two failure modes:

- Multi-query (`enable_embeddings=False` with multiple vectors): the
  per-query `namespace` was silently dropped, so every search routed to
  the default namespace and returned data from the wrong scope.
- Single-query: `query_many` internally calls
  `self.query(**query, namespace=namespace)`, which raised
  `TypeError: got multiple values for keyword argument 'namespace'`.

Move `namespace` from each query dict onto `query_many`'s top-level
kwarg, matching the Upstash client signature
(upstash_vector.core.index_operations.IndexOperations.query_many,
v0.8.0).

Closes mem0ai#4207
@CLAassistant

CLAassistant commented May 20, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@gaurav0107

Copy link
Copy Markdown
Contributor Author

Friendly check-in on this one — the fix is small (move namespace to the query_many top-level kwarg, matching the Upstash client signature), CLA is signed, tests pass locally, and the only failing check is the Vercel preview-deploy (auth, not a code issue). Happy to rebase onto current main or split the test into a separate file if that helps reviewers — just let me know what would make this easier to land.

Thanks for taking a look when you get a chance!

@kartik-mem0

Copy link
Copy Markdown
Contributor

LGTM

Linked issue: #4207 (P1-high) — validated
Bug reproduction: Confirmed via code tracing — query_many takes namespace as a top-level kwarg, not per-query. Passing it per-query caused TypeError on single-vector search and silent wrong-namespace routing on multi-vector search.
Pre-push gate: ruff lint clean, isort clean, 19/19 tests pass
Independent review: approved (separate unbiased reviewer)
Upstash API verification: Checked against current Upstash Vector Python SDK docs — namespace is indeed a top-level query_many parameter, not part of the per-query QueryRequest dict.

The fix is minimal and correct: moves namespace from each per-query dict to the query_many(namespace=...) top-level kwarg, matching how every other method in the same file (upsert, delete, update, fetch, resumable_query, reset) already passes it. The new test_search_vectors_multi_query_namespace_at_top_level regression test is thorough — it verifies both the call shape and the result flattening across multiple query response lists.

Optional (pre-existing, not introduced by this PR):

  • tests/vector_stores/test_upstash_vector.py:134 has a stray print("filters", filters) debug statement
  • mem0/vector_stores/upstash_vector.py has a minor ruff format drift (pre-existing)

Ready for human review and merge.

@kartik-mem0
kartik-mem0 merged commit d6347f6 into mem0ai:main Jun 10, 2026
7 of 8 checks passed
kartik-mem0 added a commit that referenced this pull request Jun 10, 2026
Python v2.0.5 additions:
- feat: add explain=True search score breakdowns (#5102)
- fix(memory): reject empty/whitespace search queries (#5258)
- fix(llms/xai): forward tools, add XAIConfig, parse tool_calls (#5190)
- fix(pgvector): use open=False to prevent ConnectionPool hang in Docker (#5155)
- fix(vector-stores): filter S3 vector list results client-side (#5018)
- fix(vector_stores): Upstash namespace passed as top-level kwarg (#5202)

TypeScript v3.0.7 additions:
- feat: add explain search score breakdowns (#5102)
- fix(embeddings): request float encoding_format from OpenAI (#5170)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UpstashVector.search uses namespace inside each query, breaking upstash_vector.query_many

3 participants