{"record":{"id":"1c5483dee693ec6e","repo":"666ghj/MiroFish","slug":"a-zep-batch-cannot-contain-more-than-50-000-items","errorCode":null,"errorMessage":"A Zep batch cannot contain more than 50,000 items","messagePattern":"A Zep batch cannot contain more than 50,000 items","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"backend/app/services/graph_builder.py","lineNumber":575,"sourceCode":"                ) 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,\n                    limit=100,\n                    cursor=cursor,\n                ),\n                operation_name=f\"list batch items {batch_id}\",","sourceCodeStart":557,"sourceCodeEnd":593,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/services/graph_builder.py#L557-L593","documentation":"ValueError from validate_batch_chunks: more than 50,000 chunks were produced for a single Zep batch, exceeding the Batch API's total item ceiling. Like the other checks it runs before the first Cloud mutation, so nothing is created; the caller must split the work across multiple batches or reduce chunk count.","triggerScenarios":"Very large documents combined with small chunk_size (e.g. 50M chars at chunk_size 1000 → 50k+ chunks); chunk_size/chunk_overlap misconfigured (tiny chunks) exploding the count; concatenating multiple documents into one build call.","commonSituations":"Users uploading book-scale corpora in one project; a UI or config change lowering chunk_size without accounting for the item cap; automated pipelines feeding ever-growing transcripts into a single build.","solutions":["Increase chunk_size (and adjust overlap) so total chunks fall under 50,000 for the same text.","Or split the document into multiple build operations, each under the cap, and merge at the graph level.","Add a pre-flight estimate at the API layer: expected_chunks ≈ ceil(len(text) / (chunk_size - overlap)) and reject early with guidance.","Log text length and chunk parameters whenever this fires to spot misconfiguration patterns."],"exampleFix":"# before\nchunks = TextProcessor.split_text(text, chunk_size=chunk_size, overlap=chunk_overlap)\nbuilder.validate_batch_chunks(chunks, batch_size=batch_size)\n\n# after - pre-flight estimate with an actionable message, then shard if still over\nestimated = -(-len(text) // max(1, chunk_size - chunk_overlap))\nif estimated > 50_000:\n    raise ValueError(\n        f\"Document would produce ~{estimated} chunks; Zep allows 50,000 per batch. \"\n        \"Increase chunk_size or split the document into multiple builds.\"\n    )\nchunks = TextProcessor.split_text(text, chunk_size=chunk_size, overlap=chunk_overlap)\nbuilder.validate_batch_chunks(chunks, batch_size=batch_size)","handlingStrategy":"validation","validationCode":"estimated = -(-len(text) // max(1, chunk_size - chunk_overlap))\nif estimated > 50_000:\n    raise ValueError(f'Document would produce ~{estimated} chunks; Zep caps batches at 50,000 items. Increase chunk_size or split the build.')\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 '50,000' in str(e):\n        chunk_size = max(chunk_size, math.ceil(len(text) / 49_000))  # enlarge chunks to fit, then re-split\n        chunks = TextProcessor.split_text(text, chunk_size=chunk_size, overlap=chunk_overlap)\n        builder.validate_batch_chunks(chunks, batch_size=batch_size)\n    else:\n        raise","preventionTips":["Pre-flight estimate chunk count from text length and chunk parameters before splitting.","Shard book-scale corpora into multiple build operations instead of one giant batch.","Watch chunk_size changes in config/UI — lowering it silently multiplies chunk count.","Enforce an upload size ceiling at the API layer that keeps expected chunks under the cap."],"tags":["backend","python","zep","validation","limit","large-input"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}