cocoindex-io/cocoindex · error · ValueError

Unsupported dense vector dtype {dtype!r}; zvec dense vectors

Error message

Unsupported dense vector dtype {dtype!r}; zvec dense vectors must be float32 or float16. For compressed storage, use a float32 vector with ZvecVectorDef(quantize="int8").

What it means

zvec dense vector columns only support float32 and float16 dtypes. _dense_vector_data_type raises ValueError for any other numpy dtype (e.g. float64, bfloat16, int8), and points to ZvecVectorDef(quantize="int8") for compressed storage.

Source

Thrown at python/cocoindex/connectors/zvec/_target.py:318

    str: _zvec.DataType.ARRAY_STRING,
    int: _zvec.DataType.ARRAY_INT64,
    float: _zvec.DataType.ARRAY_DOUBLE,
    bool: _zvec.DataType.ARRAY_BOOL,
}


def _json_encoder(value: Any) -> str:
    return json.dumps(value, default=str)


def _dense_vector_data_type(dtype: np.dtype) -> Any:
    # zvec's dense vector index only accepts FP32 and FP16. For smaller storage,
    # keep an FP32 vector and set quantize on ZvecVectorDef (e.g. "int8").
    if dtype == np.float32:
        return _zvec.DataType.VECTOR_FP32
    if dtype == np.float16:
        return _zvec.DataType.VECTOR_FP16
    raise ValueError(
        f"Unsupported dense vector dtype {dtype!r}; zvec dense vectors must be "
        "float32 or float16. For compressed storage, use a float32 vector with "
        'ZvecVectorDef(quantize="int8").'
    )


def _scalar_data_type(type_info: Any) -> tuple[Any, ValueEncoder | None]:
    base_type = type_info.base_type
    if base_type in _LEAF_SCALAR_MAPPINGS:
        return _LEAF_SCALAR_MAPPINGS[base_type]
    if isinstance(type_info.variant, SequenceType):
        elem_info = analyze_type_info(type_info.variant.elem_type)
        mapped = _ARRAY_ELEM_MAPPINGS.get(elem_info.base_type)
        if mapped is not None:
            return mapped, None
    # Fallback: store complex/unknown types as a JSON string.
    return _zvec.DataType.STRING, _json_encoder

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Cast vectors to np.float32 (v.astype(np.float32)) before indexing
  2. Or use np.float16 if half precision is acceptable
  3. For smaller storage, keep float32 and set ZvecVectorDef(quantize="int8")

Example fix

// before
vec: Annotated[np.ndarray, VectorSchema(size=768)]  # float64 from model
// after
vec: Annotated[np.ndarray, VectorSchema(size=768)] = np.zeros(768, dtype=np.float32)
Defensive patterns

Strategy: validation

Validate before calling

assert vectors.dtype in (np.float32, np.float16), f"unsupported dtype {vectors.dtype}; cast to float32"

Type guard

def is_zvec_vector_dtype(a: np.ndarray) -> bool:
    return a.dtype in (np.float32, np.float16)

Try / catch

try:
    schema = ZvecCollection.from_class(Row)
except ValueError as e:
    if "Unsupported dense vector dtype" in str(e):
        vectors = vectors.astype(np.float32)
    else:
        raise

Prevention

When it happens

Trigger: Declaring a vector column whose numpy ndarray annotation/override has dtype float64, bfloat16, int8, etc., resolved via _resolve_column in from_class.

Common situations: Embeddings produced by a model/lib in float64 or bfloat16 passed straight through; loading vectors with np.array without dtype=float32.

Related errors


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