cocoindex-io/cocoindex · error · ValueError

Unsupported Qdrant distance metric: {distance}

Error message

Unsupported Qdrant distance metric: {distance}

What it means

The Qdrant connector maps user-friendly distance strings to qdrant_client Distance enums. Only "cosine", "dot"/"dotproduct", and "euclid"/"euclidean"/"l2" are accepted; any other string in QdrantVectorDef.distance raises this ValueError at collection creation time.

Source

Thrown at python/cocoindex/connectors/qdrant/_target.py:666

def _collection_exists(client: QdrantClient, collection_name: str) -> bool:
    if hasattr(client, "collection_exists"):
        return bool(client.collection_exists(collection_name))
    try:
        client.get_collection(collection_name)
        return True
    except Exception:
        return False


def _distance_from_spec(distance: str) -> qdrant_models.Distance:
    distance_key = distance.lower()
    if distance_key in ("cosine",):
        return qdrant_models.Distance.COSINE
    if distance_key in ("dot", "dotproduct"):
        return qdrant_models.Distance.DOT
    if distance_key in ("euclid", "euclidean", "l2"):
        return qdrant_models.Distance.EUCLID
    raise ValueError(f"Unsupported Qdrant distance metric: {distance}")


def _multivector_comparator(
    comparator: str,
) -> qdrant_models.MultiVectorComparator:
    """Convert multivector comparator string to Qdrant enum."""
    if comparator.lower() == "max_sim":
        return qdrant_models.MultiVectorComparator.MAX_SIM
    raise ValueError(f"Unsupported multivector comparator: {comparator}")


def _sparse_modifier_from_spec(
    modifier: Literal["idf"] | None,
) -> qdrant_models.Modifier | None:
    if modifier is None:
        return None
    if modifier == "idf":
        return qdrant_models.Modifier.IDF

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Change distance to one of: "cosine", "dot", "dotproduct", "euclid", "euclidean", "l2".
  2. Lowercase the value before passing (matching is case-sensitive and exact).
  3. If you need a metric Qdrant does not support via this helper (e.g. manhattan), pick the closest supported one or implement it client-side.

Example fix

// before
QdrantVectorDef(schema=vec, distance="Cosine")
// after
QdrantVectorDef(schema=vec, distance="cosine")
Defensive patterns

Strategy: validation

Validate before calling

_ALLOWED = {"cosine", "dot", "dotproduct", "euclid", "euclidean", "l2"}
assert distance in _ALLOWED, f"distance must be one of {sorted(_ALLOWED)}, got {distance!r}"

Type guard

distance in {"cosine", "dot", "dotproduct", "euclid", "euclidean", "l2"}

Try / catch

try:
    schema = await CollectionSchema.create(vectors=QdrantVectorDef(schema=vec, distance=dist))
except ValueError as e:
    log.error("bad distance %r", dist)
    raise

Prevention

When it happens

Trigger: Setting `distance=` on QdrantVectorDef to an unsupported string, e.g. "Cosine" (capitalized), "manhattan", "hamming", or an empty string; the value flows through _vector_params_from_def -> _distance_from_spec when the collection is created.

Common situations: Copying distance names from another vector DB (e.g. "ip" from Milvus, "inner_product"); YAML config with capitalized or hyphenated values like "Cosine" or "cosine-dist"; typo such as "cosin".

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/c9601ef10acf3e26. Report an issue: GitHub.