cocoindex-io/cocoindex · error · ValueError
zvec collections require at least one vector field (dense or
Error message
zvec collections require at least one vector field (dense or sparse).
What it means
collection_target() validates that the declared schema has at least one vector field (dense or sparse) besides the primary key, since zvec is a vector collection store. A schema of only scalar columns raises ValueError.
Source
Thrown at python/cocoindex/connectors/zvec/_target.py:966
Args:
db: A ContextKey for the ManagedConnection (provided via lifespan).
collection_name: Name of the collection (a subdirectory under the
connection's base path).
schema: Schema definition built via ``CollectionSchema.from_class``.
managed_by: Whether CocoIndex manages the collection lifecycle
("system") or it must already exist ("user", documents only).
"""
_validate_collection_name(collection_name)
for name in schema.columns:
if name != schema.primary_key:
_validate_identifier(name, "field name")
if not any(
col.kind in ("dense", "sparse")
for name, col in schema.columns.items()
if name != schema.primary_key
):
raise ValueError(
"zvec collections require at least one vector field (dense or sparse)."
)
key = _CollectionKey(db_key=db.key, collection_name=collection_name)
spec = _CollectionSpec(schema=schema, managed_by=managed_by)
return _collection_provider.target_state(key, spec)
def declare_collection_target(
db: ContextKey[ManagedConnection],
collection_name: str,
schema: CollectionSchema[RowT],
*,
managed_by: target.ManagedBy = target.ManagedBy.SYSTEM,
) -> "CollectionTarget[RowT, coco.PendingS]":
"""Declare a zvec collection target and return a CollectionTarget for rows."""
provider = coco.declare_target_state_with_child(
collection_target(db, collection_name, schema, managed_by=managed_by)View on GitHub (pinned to e84aa99b32)
Solutions
- Add a dense (or sparse) vector column to your record type and populate it with embeddings.
- Use a different (non-vector) target connector if you only need scalar storage.
- Check schema.columns for at least one kind in ('dense','sparse') before calling collection_target.
Example fix
// before
@dataclass
class Doc:
id: str
title: str
// after
@dataclass
class Doc:
id: str
title: str
embedding: list[float] # declared as dense vector column Defensive patterns
Strategy: validation
Validate before calling
if not any(c.kind in ("dense", "sparse") for n, c in schema.columns.items() if n != schema.primary_key):
raise ValueError("schema needs at least one vector column") Type guard
def has_vector_column(schema) -> bool:
return any(c.kind in ("dense", "sparse") for n, c in schema.columns.items() if n != schema.primary_key) Try / catch
try:
target = collection_target(db, collection_name, schema)
except ValueError as e:
logging.error("invalid zvec schema: %s", e) Prevention
- Always include an embedding (dense or sparse) column in zvec record types.
- Use a non-vector connector for scalar-only tables.
- Validate the schema before declaring the target.
When it happens
Trigger: Calling collection_target()/declare_collection_target()/mount_collection_target() with a record type whose columns are all scalar (no embedding/vector field).
Common situations: Forgetting to add the embedding column; a schema-refactoring step that removed the vector field; using a text-only table schema with a zvec backend.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Primary key column {primary_key!r} must be a scalar field, g
- zvec collections require exactly one primary key column (map
- Primary key column '{pk}' not found in columns: {list(self.c
- Row {row.id!r}: missing vector fields {sorted(missing)}.
- Unsupported metric type: {metric!r}
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/193900bd83a60ef0.
Report an issue: GitHub.