{"record":{"id":"cb5f5ae727a99649","repo":"chroma-core/chroma","slug":"all-input-documents-must-be-strings","errorCode":null,"errorMessage":"All input documents must be strings","messagePattern":"All input documents must be strings","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/utils/embedding_functions/google_embedding_function.py","lineNumber":94,"sourceCode":"            ),\n        )\n\n    def __call__(self, input: Documents) -> Embeddings:\n        \"\"\"\n        Generate embeddings for the given documents.\n\n        Args:\n            input: Documents to generate embeddings for.\n\n        Returns:\n            Embeddings for the documents.\n        \"\"\"\n        if not input:\n            raise ValueError(\"Input documents cannot be empty\")\n        if not isinstance(input, (list, tuple)):\n            raise ValueError(\"Input must be a list or tuple of documents\")\n        if not all(isinstance(doc, str) for doc in input):\n            raise ValueError(\"All input documents must be strings\")\n\n        from google.genai.types import EmbedContentConfig\n\n        config = EmbedContentConfig(\n            task_type=self.task_type,\n            output_dimensionality=self.dimension,\n        )\n\n        try:\n            response = self.client.models.embed_content(\n                model=self.model_name,\n                contents=input,\n                config=config,\n            )\n        except Exception as e:\n            raise ValueError(f\"Failed to generate embeddings: {str(e)}\") from e\n\n        # Validate response structure","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/utils/embedding_functions/google_embedding_function.py#L76-L112","documentation":"GoogleGeminiEmbeddingFunction.__call__ verifies every element of the input is a str. Non-string entries (ints, floats, None, bytes, dicts) are rejected because this embedding function is text-only: the Gemini text-embedding models have no defined behavior for other payloads, and silently coercing them could corrupt embeddings.","triggerScenarios":"Passing a list like ['doc one', 42]; None entries where source data had missing fields; image bytes (e.g. PIL/PNG data) intended for a multimodal model; JSON rows where a 'content' field is null or a nested object; mixed id/text columns accidentally zipped together.","commonSituations":"DataFrame column containing NaN/None passed after .tolist(); upstream JSON with null content fields not sanitized; attempting multimodal (image+text) retrieval with a text-only embedding function.","solutions":["Sanitize None/missing values before embedding: [d for d in docs if isinstance(d, str)] or fill defaults","Coerce only when lossless and intended: [str(d) for d in docs]","For images use an embedding function that supports multimodal input instead of this one"],"exampleFix":"# before\nvecs = ef([\"doc one\", None, 42])  # ValueError: All input documents must be strings\n\n# after\ndocs = [d for d in [\"doc one\", None, 42] if isinstance(d, str)]\nvecs = ef(docs)","handlingStrategy":"type-guard","validationCode":"docs = [d for d in docs if isinstance(d, str)]\nassert docs, \"no string documents left after filtering\"\nvecs = ef(docs)","typeGuard":"from typing import Any, TypeGuard\n\ndef is_all_strings(docs: Any) -> TypeGuard[list[str]]:\n    return isinstance(docs, (list, tuple)) and all(isinstance(d, str) for d in docs)","tryCatchPattern":null,"preventionTips":["Sanitize DataFrame columns: df['text'] = df['text'].fillna('') or drop NA rows before .tolist()","Validate JSON records for null/numeric content fields upstream","Never feed image bytes to a text-only embedding function; use a multimodal EF"],"tags":["gemini","input-validation","type-error","chroma"],"backgroundTag":"invalid-input-type","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}