{"record":{"id":"c7afe769c0ead9ca","repo":"chroma-core/chroma","slug":"sparsevector-values-must-be-numbers-got-type-val","errorCode":null,"errorMessage":"SparseVector values must be numbers, got {type(val).__name__} at position {i}","messagePattern":"SparseVector values must be numbers, got (.+?) at position (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/base_types.py","lineNumber":73,"sourceCode":"            if len(self.labels) != len(self.indices):\n                raise ValueError(\n                    f\"SparseVector labels must have the same length as indices and values, \"\n                    f\"got {len(self.labels)} labels, {len(self.indices)} indices\"\n                )\n\n        for i, idx in enumerate(self.indices):\n            if not isinstance(idx, int):\n                raise ValueError(\n                    f\"SparseVector indices must be integers, got {type(idx).__name__} at position {i}\"\n                )\n            if idx < 0:\n                raise ValueError(\n                    f\"SparseVector indices must be non-negative, got {idx} at position {i}\"\n                )\n\n        for i, val in enumerate(self.values):\n            if not isinstance(val, (int, float)):\n                raise ValueError(\n                    f\"SparseVector values must be numbers, got {type(val).__name__} at position {i}\"\n                )\n\n        # Validate indices are sorted in strictly ascending order\n        if len(self.indices) > 1:\n            for i in range(1, len(self.indices)):\n                if self.indices[i] <= self.indices[i - 1]:\n                    raise ValueError(\n                        f\"SparseVector indices must be sorted in strictly ascending order, \"\n                        f\"found indices[{i}]={self.indices[i]} <= indices[{i-1}]={self.indices[i-1]}\"\n                    )\n\n    def to_dict(self) -> Dict[str, Any]:\n        \"\"\"Serialize to transport format with type tag.\n\n        Note: Uses 'tokens' as the wire format key name for compatibility\n        with the protobuf schema, even though the Python attribute is 'labels'.\n        \"\"\"","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/base_types.py#L55-L91","documentation":"SparseVector.__post_init__ requires every element of `values` to be an instance of Python `int` or `float`. Crucially, NumPy float scalars (np.float32, np.float64) are NOT subclasses of Python float, so numerically valid values pulled element-wise from a NumPy array still fail. None and strings fail as well. The message reports the offending type and position.","triggerScenarios":"values taken element-wise from a NumPy array (arr[i] gives np.float32/np.float64); TfidfTransformer/sklearn outputs left as NumPy scalars; dicts parsed from JSON containing null or string numbers ('0.5') in the values slot.","commonSituations":"Sparse values from TF-IDF or BM25 pipelines that return NumPy matrices; values round-tripped through pandas; optional weights serialized as null/empty-string and passed through unmodified.","solutions":["Convert before constructing: values = [float(v) for v in values] (float() accepts int, np.float32/64).","Call .tolist() on the NumPy array holding the values to get native floats.","Sanitize upstream: replace None/'' with 0.0 or drop the (index, value) pair before building the vector."],"exampleFix":"// before\nvals = [tfidf_matrix[0, j] for j in cols]  # np.float32 elements\nsv = SparseVector(indices=cols, values=vals)  # ValueError: got float32\n\n// after\nvals = [float(tfidf_matrix[0, j]) for j in cols]\nsv = SparseVector(indices=cols, values=vals)","handlingStrategy":"validation","validationCode":"# Normalize values before constructing SparseVector\nvalues = [float(v) for v in values]  # np.float32/np.float64/int -> float\n\nassert all(isinstance(v, (int, float)) for v in values)\nsv = SparseVector(indices=indices, values=values)","typeGuard":"def is_numeric_value_list(xs: object) -> bool:\n    \"\"\"Matches Chroma's check: isinstance(v, (int, float)) for every element.\"\"\"\n    return isinstance(xs, list) and all(isinstance(v, (int, float)) for v in xs)","tryCatchPattern":"try:\n    sv = SparseVector(indices=indices, values=values)\nexcept ValueError as e:\n    raise ValueError(f'invalid sparse values for doc {doc_id}: {e}') from e","preventionTips":["Convert NumPy matrix rows with [float(x) for x in row] or .tolist(); never index arrays element-wise straight into Chroma.","Reject or default None/'' weights upstream - decide the missing-value policy once.","Test with the actual sklearn/torch outputs you will ship to production."],"tags":["sparse-vector","type-validation","numpy"],"backgroundTag":"sparse-vector-validation","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}