cocoindex-io/cocoindex · error · ValueError

Row {row.id!r}: schema declares named vectors ({sorted(vecto

Error message

Row {row.id!r}: schema declares named vectors ({sorted(vector_field_names)}) but row.vector is not a dict.

What it means

The turbopuffer connector's `_row_to_upsert` builds the wire payload for each Row. When the namespace schema declares named vectors (a dict of vector fields), the connector requires `row.vector` to be a dict mapping vector field name to vector data. Passing anything else (a single sequence, ndarray, or scalar) makes the row shape incompatible with the schema, so a ValueError is raised before any network call.

Source

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

    id: _RowId
    vector: Sequence[float] | np.ndarray | dict[str, Sequence[float] | np.ndarray]
    attributes: dict[str, Any] | None = None


def _vector_to_list(v: Sequence[float] | np.ndarray) -> list[float]:
    if isinstance(v, np.ndarray):
        return v.tolist()  # type: ignore[no-any-return]
    return list(v)


def _row_to_upsert(row: Row, schema: NamespaceSchema) -> dict[str, Any]:
    """Convert a Row to the dict shape turbopuffer's write API expects."""
    out: dict[str, Any] = {"id": row.id}

    if isinstance(schema.vectors, _ResolvedNamedVectorsDef):
        vector_field_names = set(schema.vectors.vectors)
        if not isinstance(row.vector, dict):
            raise ValueError(
                f"Row {row.id!r}: schema declares named vectors "
                f"({sorted(vector_field_names)}) but row.vector is not a dict."
            )
        missing = vector_field_names - set(row.vector)
        if missing:
            raise ValueError(
                f"Row {row.id!r}: missing vector fields {sorted(missing)}."
            )
        for name, vec in row.vector.items():
            out[name] = _vector_to_list(vec)
    else:
        vector_field_names = {_DEFAULT_VECTOR_FIELD}
        if isinstance(row.vector, dict):
            raise ValueError(
                f"Row {row.id!r}: schema declares a single unnamed vector but "
                f"row.vector is a dict."
            )

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Wrap the vector in a dict keyed by the declared vector field name: Row(id=..., vector={"title_vec": [0.1, 0.2], "body_vec": [...]})
  2. Check `sorted(schema.vectors.vectors)` to confirm the exact field names the schema expects before building rows.
  3. If you actually only need one vector, change the schema to a single VectorDef instead of a named-vectors dict so a plain sequence is accepted.

Example fix

// before
row = Row(id=42, vector=np.array([0.1, 0.2, 0.3]))

// after
row = Row(id=42, vector={"title_vec": np.array([0.1, 0.2, 0.3]), "body_vec": [0.4, 0.5, 0.6]})
Defensive patterns

Strategy: type-guard

Validate before calling

named = isinstance(schema.vectors, _ResolvedNamedVectorsDef)
if named and not isinstance(row.vector, dict):
    raise TypeError(f"Row {row.id}: expected dict of named vectors")

Type guard

def is_named_vector_dict(v: object) -> TypeGuard[dict[str, Sequence[float] | np.ndarray]]:
    return isinstance(v, dict)

Try / catch

try:
    out = await component.reconcile(row)
except ValueError as e:
    if "row.vector is not a dict" in str(e):
        row = replace(row, vector=as_named_dict(row.vector, schema))
    else:
        raise

Prevention

When it happens

Trigger: Declaring a NamespaceSchema with `vectors={"title_vec": ..., "body_vec": ...}` (a _ResolvedNamedVectorsDef) but constructing Row(id=..., vector=[0.1, 0.2]) or Row(id=..., vector=np.array([...])) instead of a dict, then calling reconcile / writing the row.

Common situations: Migrating a namespace from a single unnamed vector to named vectors while reusing the old Row construction code; copying examples for single-vector namespaces into a multi-vector app; passing an embedding returned by a single-vector model directly into a named-vector schema.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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