{"record":{"id":"1d7a24e942a16049","repo":"666ghj/MiroFish","slug":"zep-batch-item-exceeds-10-000-characters-at-chunk","errorCode":null,"errorMessage":"Zep batch item exceeds 10,000 characters at chunk {oversized[0]}","messagePattern":"Zep batch item exceeds 10,000 characters at chunk (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/app/services/graph_builder.py","lineNumber":578,"sourceCode":"            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,\n                    limit=100,\n                    cursor=cursor,\n                ),\n                operation_name=f\"list batch items {batch_id}\",\n            )\n            items.extend(getattr(page, \"items\", None) or [])\n            next_cursor = getattr(page, \"next_cursor\", None)","sourceCodeStart":560,"sourceCodeEnd":596,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/services/graph_builder.py#L560-L596","documentation":"Raised by GraphBuilder.validate_batch_chunks, a pre-flight check that runs before any Zep Cloud mutation. Zep's Batch API rejects individual text items longer than 10,000 characters, so this guard fails fast with the index of the first offending chunk instead of letting the whole batch fail server-side after submission. It is a ValueError raised entirely client-side, so hitting it means no API quota was consumed and no partial state was created in Zep.","triggerScenarios":"Calling the batch-ingestion path (validate_batch_chunks) with a chunk list where at least one element exceeds 10,000 characters. Typically caused by a chunker that did not split a long document (e.g., a single huge section, min-chunk-size set above 10k, or a document with no natural split points such as one giant paragraph or table dump).","commonSituations":"Loading an unusually long flat file (logs, CSV, concatenated JSON), changing chunk_size/chunk_overlap configuration upward, feeding non-chunked text for testing, or a chunker bug that yields the whole document as one chunk. Also appears after switching embedding strategies that assume larger contexts.","solutions":["Reduce the chunker's max chunk size so no chunk exceeds 10,000 characters (e.g. chunk_size=2000 with an overlap), then rebuild.","Inspect the offending chunk (the message reports its index) to find why it was not split — often a single line/paragraph with no separator; enable hard character-based splitting as a fallback.","If the text is legitimately monolithic (one giant string with no separators), force character-window splitting at the API boundary before validate_batch_chunks."],"exampleFix":"// before\nchunks = [document_text]  # single 80k-char document\nGraphBuilder.validate_batch_chunks(chunks)\n# after\nchunk_size = 4000\nchunks = [document_text[i:i + chunk_size]\n          for i in range(0, len(document_text), chunk_size)]\nGraphBuilder.validate_batch_chunks(chunks)","handlingStrategy":"validation","validationCode":"def chunks_within_limit(chunks: list[str], limit: int = 10_000) -> bool:\n    return all(len(c) <= limit for c in chunks)\n\n# before ingestion:\nassert chunks_within_limit(chunks), 'split chunks to <=10000 chars'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Cap chunker max size well below 10,000 characters (e.g. 2,000-4,000) with a hard character-split fallback.","Run validate_batch_chunks as the last step of the chunking pipeline so failures surface before any network call.","Add a unit test feeding one oversized monolithic document to the chunker."],"tags":["zep","batch-api","validation","pre-flight","chunking"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}