What happened
QdrantVectorStore never stores the native collection name it resolved. It re-derives it from the config on every open:
def _build_collection_handle(self, namespace, name, config):
return QdrantVectorStoreCollection(
collection_name=QdrantVectorStore._build_native_collection_name(namespace, config),
...
and the name is f"{namespace}__{sha256(config.model_dump_json())}".
So the native collection a logical collection resolves to is a function of how VectorStoreCollectionConfig serializes today, not of what it resolved to when the data was written. Any change to that serialization silently repoints every existing collection at a different name — which does not exist, so the next write creates it empty.
Changes that do this, none of which look dangerous at review time:
- adding a field to
VectorStoreCollectionConfig, even an optional one with a default
- changing an existing field's default
- reordering fields
- anything that alters pydantic's
model_dump_json() output, including a pydantic upgrade
The symptom is not an error. Reads return nothing, writes succeed into a new empty collection, and the original data is still on disk under the old name with nothing pointing at it.
Expected
A collection's identity is fixed when it is created. Later changes to config serialization must not be able to move it.
Fix
Store the resolved native collection name in the registry entry at creation and use the stored value on open, instead of recomputing a hash. #1527 does this — the entry gains native_collection_name, pinned at registration.
Notes
Related but distinct from #1535, which is about indexed_properties_schema being part of collection identity at all. This issue is narrower: even if the identity inputs are agreed to be right, deriving the name at open time rather than storing it makes the mapping unstable across versions.
What happened
QdrantVectorStorenever stores the native collection name it resolved. It re-derives it from the config on every open:and the name is
f"{namespace}__{sha256(config.model_dump_json())}".So the native collection a logical collection resolves to is a function of how
VectorStoreCollectionConfigserializes today, not of what it resolved to when the data was written. Any change to that serialization silently repoints every existing collection at a different name — which does not exist, so the next write creates it empty.Changes that do this, none of which look dangerous at review time:
VectorStoreCollectionConfig, even an optional one with a defaultmodel_dump_json()output, including a pydantic upgradeThe symptom is not an error. Reads return nothing, writes succeed into a new empty collection, and the original data is still on disk under the old name with nothing pointing at it.
Expected
A collection's identity is fixed when it is created. Later changes to config serialization must not be able to move it.
Fix
Store the resolved native collection name in the registry entry at creation and use the stored value on open, instead of recomputing a hash. #1527 does this — the entry gains
native_collection_name, pinned at registration.Notes
Related but distinct from #1535, which is about
indexed_properties_schemabeing part of collection identity at all. This issue is narrower: even if the identity inputs are agreed to be right, deriving the name at open time rather than storing it makes the mapping unstable across versions.