Skip to content

fix(retrieval): return no matches instead of erroring when the vector collection doesn't exist yet - #843

Open
EnjoyBacon7 wants to merge 1 commit into
developfrom
fix/retrieval-missing-collection
Open

fix(retrieval): return no matches instead of erroring when the vector collection doesn't exist yet#843
EnjoyBacon7 wants to merge 1 commit into
developfrom
fix/retrieval-missing-collection

Conversation

@EnjoyBacon7

@EnjoyBacon7 EnjoyBacon7 commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

What

search()/multi_query_search() on VectorStoreSearcher raise instead of
returning an empty result when the shared Milvus collection doesn't exist yet.

Root cause

The shared collection (config.vectordb.collection_name) is created lazily
on the first indexed file system-wide (services/workers/stages/store.py).
On a fresh deployment — or any retrieval-needing chat/search query before
that first file is indexed, regardless of partition — Milvus raises
CollectionNotExists, wrapped as VDBSearchError, and propagates as a real
error instead of "no matches."

This is the same class of bug #508 already fixed for delete_partition
(PartitionService), using the existing VectorStore.collection_exists()
port method as the guard. That fix only covered delete; search was still
exposed.

Fix

Mirror #508's pattern in VectorStoreSearcher.search() and
multi_query_search(): check collection_exists() before embedding/
searching, and return [] immediately if the collection is absent — no
collection means no chunks to find, and skipping straight to an empty result
also avoids an unnecessary embedding-API call.

Test

Adds test_search_returns_empty_when_collection_does_not_exist and
test_multi_query_search_returns_empty_when_collection_does_not_exist,
asserting the embedder and store are never called when the collection is
absent. Full unit suite: 2433 passed (1 pre-existing unrelated failure on
develop, unaffected by this change), ruff clean, layer-import guard clean.

Summary by CodeRabbit

  • Bug Fixes

    • Searches now safely return no results when the configured vector collection is unavailable.
    • Prevents unnecessary processing and search attempts for missing collections.
  • Tests

    • Added coverage for standard and multi-query searches when collections do not exist.

… collection doesn't exist yet

The shared Milvus collection is created lazily on the first indexed
file system-wide. On a fresh deployment, or any query before that
first index, search/multi_query_search raised CollectionNotExists ->
VDBSearchError instead of returning an empty result — the same class
of bug #508 already fixed for delete_partition.
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The vector-store search methods now check collection existence before embedding or retrieval. Missing collections return empty results. Unit tests cover both search methods and update existing mocks for the collection-present path.

Changes

Vector collection guard

Layer / File(s) Summary
Search collection guards
openrag/services/storage/vector_store_searcher.py
search and multi_query_search check whether the configured collection exists. Both return an empty list before embedding or retrieval when it does not.
Search guard regression tests
tests/unit/services/storage/test_vector_store_searcher.py
Tests verify empty results and no embedding or search calls for missing collections. Existing fixtures mark collections as present.
Estimated code review effort: 2 (Simple) ~10 minutes

Possibly related PRs

  • linagora/openrag#842: Modifies the same search methods and tests for missing vector-store collections.

Suggested reviewers: hedhoud, aditykris

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: returning no matches when the vector collection does not exist.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/retrieval-missing-collection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openrag/services/storage/vector_store_searcher.py`:
- Around line 72-74: Update the search flow in VectorStoreSearcher to handle a
collection being dropped between collection_exists() and search(). Prefer an
atomic store-level search operation; otherwise catch the store’s
missing-collection error around search and return [] while preserving
VDBSearchError translation for other failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 74edc257-317a-4801-9533-ae2ba9ffc389

📥 Commits

Reviewing files that changed from the base of the PR and between 88da8b4 and da5fc35.

📒 Files selected for processing (2)
  • openrag/services/storage/vector_store_searcher.py
  • tests/unit/services/storage/test_vector_store_searcher.py

Comment on lines +72 to +74
# Collection is created lazily on first insert (#508); absent means no chunks.
if not await self._store.collection_exists(self._collection):
return []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Expect either no concurrent collection-drop path or explicit missing-collection handling.
rg -n -C 8 'drop_collection|release_collection|has_collection|collection_exists|VDBSearchError' openrag tests

Repository: linagora/openrag

Length of output: 50372


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Inspect the relevant searcher/store implementation and exception shape without running repo code.
sed -n '1,150p' openrag/services/storage/vector_store_searcher.py
printf '\n--- exceptions around VDBSearchError / VDBPartitionNotFound ---\n'
sed -n '35,46p' openrag/core/utils/exceptions.py
sed -n '400,412p' openrag/core/utils/exceptions.py
printf '\n--- Milvus search wrappers and collection drop/resolvers ---\n'
sed -n '800,1105p' openrag/services/storage/milvus_store.py
sed -n '880,980p' openrag/services/storage/milvus_store.py

Repository: linagora/openrag

Length of output: 23633


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Find all search_call sites around collection_exists and whether they catch missing-collection errors.
rg -n -C 4 'collection_exists\(.*collection|\.search\(|\.hybrid_search\(' openrag/services/storage/vector_store_searcher.py openrag/services/storage/milvus_store.py tests/integration/repos/test_milvus_store_integration.py tests/integration/repos/test_workspace_scoping_e2e.py

Repository: linagora/openrag

Length of output: 12540


Handle collection absence atomically in search.

collection_exists() and search() are separate calls. If drop_collection() runs concurrently, search() can still translate the missing collection failure to VDBSearchError. Make the store operation atomic, or catch the missing-collection state at VectorStoreSearcher and return an empty result.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openrag/services/storage/vector_store_searcher.py` around lines 72 - 74,
Update the search flow in VectorStoreSearcher to handle a collection being
dropped between collection_exists() and search(). Prefer an atomic store-level
search operation; otherwise catch the store’s missing-collection error around
search and return [] while preserving VDBSearchError translation for other
failures.

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.

1 participant