cocoindex-io/cocoindex · error · ValueError

Qdrant sparse vectors are always named; pass them in a dict,

Error message

Qdrant sparse vectors are always named; pass them in a dict, e.g. vectors={"sparse": QdrantSparseVectorDef()}

What it means

Raised in `create` when a bare `QdrantSparseVectorDef` is passed as `vectors`. Qdrant sparse vectors must live under a name; unnamed (single, default) vectors only support dense vectors. The fix is to wrap the sparse definition in a dict with an explicit name.

Source

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

        | dict[str, QdrantVectorDef | QdrantSparseVectorDef]
        | None = None,
    ) -> "CollectionSchema":
        """
        Create a CollectionSchema by resolving vector definitions.

        Args:
            vectors: Either a single QdrantVectorDef (for an unnamed dense
                     vector) or a dictionary mapping vector names to
                     QdrantVectorDef or QdrantSparseVectorDef. Dense and
                     sparse vectors share one namespace in Qdrant, so both
                     kinds live in the same dict; sparse vectors are always
                     named.
        """
        resolved: _ResolvedQdrantVectorDef | _ResolvedQdrantNamedVectorsDef
        if isinstance(vectors, QdrantVectorDef):
            resolved = await _resolve_vector_def(vectors)
        elif isinstance(vectors, QdrantSparseVectorDef):
            raise ValueError(
                "Qdrant sparse vectors are always named; pass them in a dict, "
                'e.g. vectors={"sparse": QdrantSparseVectorDef()}'
            )
        elif isinstance(vectors, dict):
            if not vectors:
                raise ValueError("Qdrant named vectors must not be empty")
            _validate_vector_names(vectors.keys(), "vector")
            resolved_entries: dict[
                str, _ResolvedQdrantVectorDef | _ResolvedQdrantSparseVectorDef
            ] = {}
            for name, vector_def in vectors.items():
                if isinstance(vector_def, QdrantVectorDef):
                    resolved_entries[name] = await _resolve_vector_def(vector_def)
                elif isinstance(vector_def, QdrantSparseVectorDef):
                    resolved_entries[name] = _resolve_sparse_vector_def(vector_def)
                else:
                    raise ValueError(f"Invalid vector definition: {vector_def}")
            resolved = _ResolvedQdrantNamedVectorsDef(vectors=resolved_entries)

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Wrap the sparse definition in a dict: `vectors={"sparse": QdrantSparseVectorDef()}`.
  2. Choose a meaningful name — points must supply their sparse vectors under that same name.

Example fix

// before
create(vectors=QdrantSparseVectorDef())
// after
create(vectors={"sparse": QdrantSparseVectorDef()})
Defensive patterns

Strategy: type-guard

Validate before calling

def vectors_arg_ok(vectors) -> bool:
    from cocoindex.connectors.qdrant._target import QdrantVectorDef, QdrantSparseVectorDef
    if isinstance(vectors, QdrantSparseVectorDef):
        return False
    return True

Type guard

def is_valid_vectors_arg(v) -> bool:
    from cocoindex.connectors.qdrant import QdrantVectorDef, QdrantSparseVectorDef
    return isinstance(v, QdrantVectorDef) or (isinstance(v, dict) and bool(v))

Try / catch

try:
    collection = await QdrantCollection.create(..., vectors=vectors)
except ValueError as e:
    if "sparse vectors are always named" in str(e):
        vectors = {"sparse": vectors}  # wrap and retry
        collection = await QdrantCollection.create(..., vectors=vectors)
    else:
        raise

Prevention

When it happens

Trigger: Calling collection `create(vectors=QdrantSparseVectorDef())` without wrapping it in a named dict.

Common situations: Porting code that used a dense default vector to sparse vectors; assuming sparse vectors follow the same single-default-vector API as dense ones.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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