Skip to content

[BUG] Qdrant metadata content overwrites the indexed document body #9129

Open

Description

@Ymmcc

Description

Qdrant document metadata containing a content key silently replaces the document text in the stored payload. The embedding is computed from document["content"], but search returns metadata["content"] as the document body. Both add_documents and aadd_documents use the same payload helper.

Reproduction

Reproduced on main at 6bd60b223101a11f7ac675706ff1ebb03314c95d (CrewAI 1.15.35), Windows, Python 3.12.15, qdrant-client 1.14.3. No server, model, or API key is needed:

from crewai.rag.qdrant.client import QdrantClient
from qdrant_client import QdrantClient as SDKClient
from qdrant_client.models import Distance, VectorParams

sdk = SDKClient(location=":memory:")
try:
    client = QdrantClient(client=sdk, embedding_function=lambda text: [1.0, 0.0, 0.0])
    client.create_collection(
        collection_name="content_repro",
        vectors_config=VectorParams(size=3, distance=Distance.COSINE),
    )
    client.add_documents(collection_name="content_repro", documents=[{
        "content": "Original document text",
        "metadata": {"content": "Metadata text", "source": "example.txt"},
    }])
    result = client.search(collection_name="content_repro", query="Original document text")[0]
    print(result["content"])
    assert result["content"] == "Original document text", result
finally:
    sdk.close()

Actual: prints Metadata text and fails the assertion. The equivalent async create/add/search sequence returns the same wrong text.

Expected: the canonical document body remains Original document text. Non-conflicting metadata such as source remains available.

Cause and proposed fix

_create_point_from_document builds {"content": doc["content"], **metadata}, so metadata wins on collision. Assigning the reserved payload content field after expanding metadata preserves the document body. This keeps the existing flat payload layout and metadata filtering behavior; it does not introduce a new metadata storage format or recover previously overwritten content.

I checked existing issues and open PRs for this collision and did not find a duplicate. A one-line fix and regression tests for mapping/list metadata and empty/nonempty text are ready. The four new cases fail before the fix; the full Qdrant test module passes (47 tests) after it. Real in-memory sync/async roundtrips were also checked.

AI disclosure

AI-generated contribution: the investigation, reproduction, proposed implementation, tests, and this report were prepared and run with an AI coding assistant at the contributor's request. Please apply the required llm-generated label if my account cannot manage repository labels.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions