cocoindex-io/cocoindex · error · ValueError

Invalid vector definition: {vectors}

Error message

Invalid vector definition: {vectors}

What it means

CollectionSchema.create() in the Qdrant connector only accepts a QdrantVectorDef, a non-empty dict of names mapped to QdrantVectorDef/QdrantSparseVectorDef, or None (which has its own clearer error). Any other value — or a dict whose per-entry value is not a recognized vector def type — raises this ValueError. It is an upfront input-validation guard so invalid schemas fail in Python instead of at Qdrant collection creation time.

Source

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

                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)
        elif vectors is None:
            raise ValueError(
                "Qdrant collection schema must declare at least one vector"
            )
        else:
            raise ValueError(f"Invalid vector definition: {vectors}")
        return cls(resolved)

    @property
    def vectors(
        self,
    ) -> _ResolvedQdrantVectorDef | _ResolvedQdrantNamedVectorsDef:
        """Get vector definitions (all VectorSchemaProviders resolved)."""
        return self._vectors


class _PointAction(NamedTuple):
    point_id: _PointId
    point: qdrant_models.PointStruct | None


class _PointHandler(coco.TargetHandler[qdrant_models.PointStruct, _PointFingerprint]):
    _client: QdrantClient
    _collection_name: str

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Wrap each vector configuration in QdrantVectorDef (or QdrantSparseVectorDef for sparse) instead of passing raw dicts or lists.
  2. If vectors is empty/None, pass at least one vector, e.g. CollectionSchema.create(vectors={"embedding": QdrantVectorDef(schema=VectorSchema(dtype=np.float32, size=384), distance="cosine")}).
  3. Pass sparse vectors only inside a dict (sparse vectors are always named in Qdrant).
  4. Print type(vectors) and each dict value's type to confirm they are the connector's def classes, not plain dicts.

Example fix

// before
await CollectionSchema.create(vectors={"embedding": {"size": 384, "distance": "cosine"}})
// after
from cocoindex.connectors.qdrant import QdrantVectorDef
await CollectionSchema.create(vectors={"embedding": QdrantVectorDef(schema=VectorSchema(dtype=np.float32, size=384), distance="cosine")})
Defensive patterns

Strategy: type-guard

Validate before calling

def _valid_vectors(v):
    from cocoindex.connectors.qdrant import QdrantVectorDef, QdrantSparseVectorDef
    if isinstance(v, QdrantVectorDef):
        return True
    return isinstance(v, dict) and bool(v) and all(
        isinstance(x, (QdrantVectorDef, QdrantSparseVectorDef)) for x in v.values()
    )
assert _valid_vectors(vectors), f"bad vectors: {type(vectors)}"

Type guard

isinstance(vectors, QdrantVectorDef) or (isinstance(vectors, dict) and all(isinstance(d, (QdrantVectorDef, QdrantSparseVectorDef)) for d in vectors.values()))

Try / catch

try:
    schema = await CollectionSchema.create(vectors=cfg["vectors"])
except ValueError as e:
    raise ConfigError(f"qdrant vectors config invalid: {e}") from None

Prevention

When it happens

Trigger: Calling `await CollectionSchema.create(vectors=...)` where `vectors` is not a QdrantVectorDef and not a dict (e.g. a list, a bare string, a QdrantSparseVectorDef handled elsewhere, or a dataclass-like object); or passing a dict whose value for some vector name is neither QdrantVectorDef nor QdrantSparseVectorDef (e.g. a raw dict or a dict of parameters).

Common situations: Hand-building the vectors config from YAML/JSON and forgetting to construct QdrantVectorDef objects; typos where a dict of plain kwargs is passed instead of the def class; mixing sparse vectors without wrapping them in QdrantSparseVectorDef inside a dict.

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/9d8767b20ba59347. Report an issue: GitHub.