{"record":{"id":"ed79493ac32a4f0f","repo":"666ghj/MiroFish","slug":"at-least-one-text-chunk-is-required","errorCode":null,"errorMessage":"At least one text chunk is required","messagePattern":"At least one text chunk is required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"backend/app/services/graph_builder.py","lineNumber":571,"sourceCode":"            )\n            if getattr(summary, \"status\", None) in {None, \"draft\"}:\n                raise RuntimeError(\n                    f\"Zep batch {batch_id} processing is unconfirmed\"\n                ) from error\n\n        return BatchSubmission(\n            batch_id=batch_id,\n            operation_id=operation_id,\n            episode_uuids=episode_uuids,\n            item_count=total_chunks,\n        )\n\n    @staticmethod\n    def validate_batch_chunks(chunks: List[str], *, batch_size: int = 350) -> None:\n        \"\"\"Validate every Batch API limit before the first Cloud mutation.\"\"\"\n\n        if not chunks:\n            raise ValueError(\"At least one text chunk is required\")\n        if not 1 <= batch_size <= 350:\n            raise ValueError(\"batch_size must be between 1 and 350\")\n        if len(chunks) > 50_000:\n            raise ValueError(\"A Zep batch cannot contain more than 50,000 items\")\n        oversized = [index for index, chunk in enumerate(chunks) if len(chunk) > 10_000]\n        if oversized:\n            raise ValueError(\n                f\"Zep batch item exceeds 10,000 characters at chunk {oversized[0]}\"\n            )\n\n    def _list_batch_items(self, batch_id: str) -> List[Any]:\n        items: List[Any] = []\n        cursor: int | None = None\n        seen_cursors: set[int] = set()\n        while True:\n            page = call_zep_read_with_retry(\n                lambda: self.client.batch.list_items(\n                    batch_id=batch_id,","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/services/graph_builder.py#L553-L589","documentation":"ValueError from the static validate_batch_chunks (graph_builder.py): the chunks list passed to a Zep batch submission is empty. Zep's Batch API requires at least one item, and the validation runs before the first Cloud mutation (per its docstring), so no graph or batch is touched when it fires.","triggerScenarios":"TextProcessor.split_text returned zero chunks because the input text was empty/whitespace; upstream filtering stripped all chunks; a caller passed an uninitialized list; resume path re-splitting edited-down-to-empty text.","commonSituations":"User submits an empty document or one containing only whitespace/punctuation removed by preprocessing; file upload silently failed and produced an empty string; OCR extraction returned nothing.","solutions":["Check the source text passed to TextProcessor.split_text — it is empty or normalizes to nothing.","Reject empty documents at the API layer (request validation) before invoking the builder.","If preprocessing removes all content, loosen the filter or surface a clearer 'document has no extractable text' error.","Log the raw document length/first bytes at intake to catch silent upload failures."],"exampleFix":"# before\nchunks = TextProcessor.split_text(text, chunk_size=chunk_size, overlap=chunk_overlap)\nbuilder.validate_batch_chunks(chunks, batch_size=350)\n\n# after - validate the source text first with a user-facing message\nif not text or not text.strip():\n    raise ValueError(\"Document text is empty; nothing to build a graph from\")\nchunks = TextProcessor.split_text(text, chunk_size=chunk_size, overlap=chunk_overlap)\nbuilder.validate_batch_chunks(chunks, batch_size=350)","handlingStrategy":"validation","validationCode":"if not text or not text.strip():\n    raise ValueError('Document text is empty; nothing to build a graph from')\nchunks = TextProcessor.split_text(text, chunk_size=chunk_size, overlap=chunk_overlap)\nbuilder.validate_batch_chunks(chunks, batch_size=batch_size)","typeGuard":null,"tryCatchPattern":"try:\n    builder.validate_batch_chunks(chunks, batch_size=batch_size)\nexcept ValueError as e:\n    if 'At least one text chunk' in str(e):\n        return HTTPException(status_code=422, detail='Uploaded document contains no extractable text')\n    raise","preventionTips":["Reject empty documents at the API layer before invoking the builder.","Log raw text length at intake to catch silent upload/extraction failures.","Unit-test the preprocessing pipeline with whitespace-only and filtered-to-empty inputs.","Never pass an uninitialized chunks list to submission; always derive it from split_text output."],"tags":["backend","python","zep","validation","empty-input"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}