Skip to content

fix(faiss): don't leave orphaned vectors when a batch repeats a document ID - #4180

Open
eric7h wants to merge 1 commit into
deepset-ai:mainfrom
eric7h:fix/faiss-overwrite-duplicate-in-batch
Open

eric7h wants to merge 1 commit into
deepset-ai:mainfrom
eric7h:fix/faiss-overwrite-duplicate-in-batch

Conversation

@eric7h

@eric7h eric7h commented Oct 31, 2026

Copy link
Copy Markdown

Related Issues

  • No existing issue; found while reading FAISSDocumentStore.write_documents.

Proposed Changes:

When one write_documents call contains the same document ID twice (e.g. with DuplicatePolicy.OVERWRITE), the FAISS index ends up with an orphaned vector.

Root cause: vectors are collected in ids_to_add_to_index / vectors_to_add and only added to the index at the end of the call. When the second copy of an ID is processed, the overwrite path calls delete_documents([doc.id]), which drops the ID mapping and calls remove_ids — but the first copy's vector is not in the index yet, so nothing is removed. Its vector is then still added at the end under an int ID that no longer maps to any document.

Effects: index.ntotal is larger than count_documents(), and search() can return fewer than top_k results, because the orphan takes a slot in FAISS's top-k and is then skipped.

store = FAISSDocumentStore(embedding_dim=2)
store.write_documents([
    Document(id="a", content="old", embedding=[0.0, 0.0]),
    Document(id="a", content="new", embedding=[0.1, 0.1]),
    Document(id="b", content="b", embedding=[5.0, 5.0]),
], policy=DuplicatePolicy.OVERWRITE)
store.count_documents(), store.index.ntotal       # (2, 3)
[d.id for d in store.search([0.0, 0.0], top_k=2)]  # ['a']  -> expected ['a', 'b']

Fix: keep the pending vectors in a dict keyed by document ID and drop the pending entry when that ID is overwritten later in the same batch.

How did you test it?

  • Added test_write_documents_overwrite_duplicate_in_same_batch_leaves_no_orphan_vector; it fails on main (ntotal == 3, search returns only a) and passes with the fix.
  • pytest tests in integrations/faiss: 103 passed, 2 skipped.
  • ruff check, ruff format --check and mypy (hatch types script) pass.

Notes for the reviewer

Small, self-contained change in write_documents; behaviour for batches without duplicate IDs is unchanged.

This PR was generated with an AI assistant. I have reviewed the changes and run the relevant tests.

Checklist

@eric7h
eric7h requested a review from a team as a code owner October 31, 2026 02:39
@eric7h
eric7h requested review from davidsbatista and removed request for a team October 31, 2026 02:39
@CLAassistant

CLAassistant commented Oct 31, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions

Copy link
Copy Markdown
Contributor

Coverage report (faiss)

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  integrations/faiss/src/haystack_integrations/document_stores/faiss
  document_store.py
Project Total  

This report was generated by python-coverage-comment-action

@HaystackBot

Copy link
Copy Markdown
Contributor

Hi @eric7h, thanks a lot for your contribution! 🙏

We noticed that the Contributor License Agreement (CLA) check (license/cla) hasn't passed yet, so we've temporarily moved this PR to draft and paused the review assignment.

To get your PR reviewed, please sign the CLA via the link in the license/cla check below (or in the CLA bot comment). As soon as the check turns green, this PR will automatically be marked ready for review again and a reviewer will be re-assigned.

@HaystackBot
HaystackBot removed the request for review from davidsbatista October 31, 2026 03:51
@HaystackBot HaystackBot added the cla-pending PR is in draft until the contributor signs the CLA label Oct 31, 2026
@HaystackBot
HaystackBot marked this pull request as draft October 31, 2026 03:51
@HaystackBot
HaystackBot marked this pull request as ready for review October 31, 2026 04:43
@HaystackBot HaystackBot removed the cla-pending PR is in draft until the contributor signs the CLA label Oct 31, 2026
@HaystackBot

Copy link
Copy Markdown
Contributor

Thanks for signing the CLA, @eric7h! 🎉 This PR is now ready for review again and the reviewer has been re-assigned.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants