Skip to content

Local alias updates partially apply a failed batch #1484

Description

@Harsh23Kashyap

Problem

QdrantClient(path=...) applies each alias operation directly to its in-memory mapping. If a later operation fails, the call raises but earlier operations remain visible until the client is closed. A persistent client then reopens with the old mapping, so reads before and after restart disagree.

This matters when switching a live alias to a new collection: a failed batch can still redirect searches to the new collection for the lifetime of the process. The server applies alias batches atomically and keeps the old mapping when it rejects an operation.

Reproducer

from qdrant_client import QdrantClient, models

client = QdrantClient(":memory:")
client.create_collection("docs_v1", vectors_config={})
client.create_collection("docs_v2", vectors_config={})
client.update_collection_aliases([
    models.CreateAliasOperation(create_alias=models.CreateAlias(
        collection_name="docs_v1", alias_name="live"
    ))
])

try:
    client.update_collection_aliases([
        models.CreateAliasOperation(create_alias=models.CreateAlias(
            collection_name="docs_v2", alias_name="live"
        )),
        models.RenameAliasOperation(rename_alias=models.RenameAlias(
            old_alias_name="missing", new_alias_name="other"
        )),
    ])
except KeyError:
    pass

print(client.get_aliases().aliases)
# [AliasDescription(alias_name='live', collection_name='docs_v2')]

Expected: the failed batch leaves live pointing at docs_v1. Actual: it points at docs_v2 in memory. With QdrantClient(path=...), closing and reopening restores docs_v1, since _save() never runs after the exception.

Both sync and async local implementations mutate self.aliases within the batch loop. The existing alias congruence test covers successful batches but not a rejected batch.

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