{"record":{"id":"7a85b105a73b0479","repo":"apache/beam","slug":"embeddableitem-does-not-contain-storable-string-content-text","errorCode":null,"errorMessage":"EmbeddableItem does not contain storable string content (text or image URI). {self}","messagePattern":"EmbeddableItem does not contain storable string content \\(text or image URI\\)\\. (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/rag/types.py","lineNumber":163,"sourceCode":"  def dense_embedding(self) -> Optional[list[float]]:\n    return self.embedding.dense_embedding if self.embedding else None\n\n  @property\n  def sparse_embedding(self) -> Optional[tuple[list[int], list[float]]]:\n    return self.embedding.sparse_embedding if self.embedding else None\n\n  @property\n  def content_string(self) -> str:\n    \"\"\"Returns storable string content for ingestion.\n\n    Falls back through content fields in priority order:\n    text > image URI.\n    \"\"\"\n    if self.content.text is not None:\n      return self.content.text\n    if isinstance(self.content.image, str):\n      return self.content.image\n    raise ValueError(\n        f'EmbeddableItem does not contain storable string content'\n        f' (text or image URI). {self}')\n\n\n# Backward compatibility alias. Existing code using Chunk continues to work\n# unchanged since Chunk IS EmbeddableItem.\nChunk = EmbeddableItem\n","sourceCodeStart":145,"sourceCodeEnd":171,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/rag/types.py#L145-L171","documentation":"EmbeddableItem.content_string derives a storable string for the item: it prefers content.text and falls back to a string image URI. If neither is present (empty text and a non-string/absent image), there is nothing storable, so it raises ValueError.","triggerScenarios":"Accessing item.content_string on an EmbeddableItem constructed with content=Content(text=None, image=<non-str or None>) — e.g. image passed as bytes instead of a URI string, or both fields left unset.","commonSituations":"Loading documents that only contain binary image data without a URI; pipeline steps that clear text before content_string is computed; constructing Chunk/EmbeddableItem with an empty Content() by mistake.","solutions":["Set content.text on the item before computing content_string","If the content is an image, pass its URI as a str in Content(image='gs://...'), not bytes","Guard with hasattr/if checks or catch ValueError and skip items without storable content","Check upstream extraction for documents that produce an empty Content"],"exampleFix":"// before\nChunk(content=Content(image=image_bytes))\n// after\nChunk(content=Content(image=\"gs://bucket/img.png\"))  # or set content.text","handlingStrategy":"try-catch","validationCode":"def has_storable_content(item) -> bool:\n    return item.content.text is not None or isinstance(item.content.image, str)","typeGuard":"def has_content_string(item) -> bool:\n    return item.content.text is not None or isinstance(item.content.image, str)","tryCatchPattern":"try:\n    text = item.content_string\nexcept ValueError:\n    logging.warning(\"No storable content for %r; skipping\", item)\n    text = None","preventionTips":["Always populate content.text during document extraction","Pass image URIs as str, never raw bytes, when constructing Content","Skip or fix items with empty Content before content-dependent transforms"],"tags":["python","rag","data-validation"],"backgroundTag":"empty-required-field","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}