{"record":{"id":"940e25248a9c8c97","repo":"cocoindex-io/cocoindex","slug":"zvecftstype-on-column-name-r-requires-a-str-fiel","errorCode":null,"errorMessage":"ZvecFtsType on column {name!r} requires a str field, got {type_info.base_type!r}.","messagePattern":"ZvecFtsType on column (.+?) requires a str field, got (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/zvec/_target.py","lineNumber":405,"sourceCode":"            data_type=_zvec.DataType.SPARSE_VECTOR_FP32,\n            nullable=type_info.nullable,\n            metric=vector_def.metric,\n        )\n\n    if type_info.base_type is np.ndarray:\n        raise ValueError(\n            f\"Vector column {name!r} requires a VectorSchema (provide it via an \"\n            \"Annotated NDArray or column_overrides).\"\n        )\n\n    # Full-text field: str marked with ZvecFtsType.\n    if fts_type is not None:\n        if zvec_type is not None:\n            raise ValueError(\n                f\"Column {name!r} cannot combine ZvecFtsType with ZvecType.\"\n            )\n        if type_info.base_type is not str:\n            raise ValueError(\n                f\"ZvecFtsType on column {name!r} requires a str field, got \"\n                f\"{type_info.base_type!r}.\"\n            )\n        return _Column(\n            name=name,\n            kind=\"fts\",\n            data_type=_zvec.DataType.STRING,\n            nullable=type_info.nullable,\n            tokenizer_name=fts_type.tokenizer_name,\n            filters=fts_type.filters,\n            extra_params=fts_type.extra_params,\n        )\n\n    # Scalar field.\n    if zvec_type is not None:\n        return _Column(\n            name=name,\n            kind=\"scalar\",","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/zvec/_target.py#L387-L423","documentation":"Type-compatibility guard for full-text columns in _resolve_column. ZvecFtsType indexes textual content, so it is only meaningful on a str field; applying it to any other base type (int, list, ndarray, etc.) would create a column the engine cannot index for full-text search. Raised during schema construction when the annotated field's resolved type is not str. Either change the field to str or remove the ZvecFtsType annotation.","triggerScenarios":"Applying ZvecFtsType to an int, bytes, list, or other non-str field in a from_class row class.","commonSituations":"Marking a numeric or binary field for full-text search by mistake; schema drift where a field changed type after FTS annotation was added.","solutions":["Change the field type to str","Remove ZvecFtsType if the field should not be searched","Cast the value to str in the producing function before indexing"],"exampleFix":"// before\ncount: Annotated[int, ZvecFtsType()]\n// after\ncount: int","handlingStrategy":"validation","validationCode":"assert isinstance(getattr(Row, field_name), property) or get_type_hints(Row)[field_name] is str, \"ZvecFtsType requires str\"","typeGuard":"def is_fts_candidate(hint: object) -> bool:\n    base = get_args(hint)[0] if get_origin(hint) is Annotated else hint\n    return base is str","tryCatchPattern":"try:\n    schema = ZvecCollection.from_class(Row)\nexcept ValueError as e:\n    if \"ZvecFtsType\" in str(e) and \"str field\" in str(e):\n        # remove ZvecFtsType or change the field to str\n        ...\n    else:\n        raise","preventionTips":["Only annotate str fields with ZvecFtsType","Cast numeric/binary data to str upstream if it should be searchable","Review annotations after field type changes"],"tags":["python","validation","type-mismatch","zvec"],"backgroundTag":"type-mismatch","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}