cocoindex-io/cocoindex · error · ValueError

Invalid vector definition: {vectors}

Error message

Invalid vector definition: {vectors}

What it means

The `vectors` argument of turbopuffer target `create()` must be either a `VectorDef` (single vector) or a non-empty dict of named `VectorDef`s. Anything else (wrong type, None, a string) falls through to the final `else` and raises ValueError showing the offending value.

Source

Thrown at python/cocoindex/connectors/turbopuffer/_target.py:161

            resolved = await _resolve_vector_def(vectors)
        elif isinstance(vectors, dict):
            if not vectors:
                raise ValueError(
                    "Named-vectors dict is empty; declare at least one vector field."
                )
            reserved = _RESERVED_VECTOR_FIELD_NAMES & set(vectors)
            if reserved:
                raise ValueError(
                    f"Vector field name {sorted(reserved)[0]!r} is reserved "
                    f"(it collides with the row id at the wire level)."
                )
            resolved = _ResolvedNamedVectorsDef(
                vectors={
                    name: await _resolve_vector_def(vd) for name, vd in vectors.items()
                }
            )
        else:
            raise ValueError(f"Invalid vector definition: {vectors}")
        return cls(resolved, distance)

    @property
    def vectors(self) -> _ResolvedVectorDef | _ResolvedNamedVectorsDef:
        return self._vectors

    @property
    def distance(self) -> DistanceMetric:
        return self._distance


@dataclass(slots=True)
class Row:
    """A document to write to a turbopuffer namespace.

    Args:
        id: Document id (string or integer).
        vector: Vector data — for an unnamed-vector schema pass a single sequence;

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Wrap the definition in a `VectorDef` (single vector) or a dict mapping names to `VectorDef` instances.
  2. Do not pass the schema name string directly — resolve it into a VectorDef first.
  3. Check the function signature/docs for the accepted `VectorDef | dict[str, VectorDef]` shape.

Example fix

// before
await Target.create(vectors="embedding_vec")
// after
await Target.create(vectors=VectorDef(schema="embedding_vec", dimension=1536))
Defensive patterns

Strategy: type-guard

Validate before calling

from cocoindex.connectors.turbopuffer._target import VectorDef
if not isinstance(vectors, (VectorDef, dict)):
    raise TypeError("vectors must be a VectorDef or dict[str, VectorDef]")

Type guard

def is_valid_vectors_arg(v) -> bool:
    from cocoindex.connectors.turbopuffer._target import VectorDef
    if isinstance(v, VectorDef):
        return True
    return isinstance(v, dict) and bool(v) and all(isinstance(x, VectorDef) for x in v.values())

Try / catch

try:
    spec = await Target.create(vectors=vectors, distance=metric)
except ValueError as e:
    if "Invalid vector definition" in str(e):
        raise TypeError(f"vectors must be VectorDef or dict[str, VectorDef], got {type(vectors)}") from e
    raise

Prevention

When it happens

Trigger: Passing `vectors=None`, a list, a string schema name, a raw dict of non-VectorDef values that somehow bypassed earlier branches (e.g. wrong-typed object), or any non-VectorDef/non-dict value to `create()`.

Common situations: Confusing the vector schema name (string) with a VectorDef object; passing a config dict straight through without constructing VectorDef entries; refactors changing the expected argument type.

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/2478431121226a42. Report an issue: GitHub.