{"record":{"id":"4d424d11d246f77e","repo":"666ghj/MiroFish","slug":"zep-batch-batch-id-item-submission-failed","errorCode":null,"errorMessage":"Zep batch {batch_id} item submission failed","messagePattern":"Zep batch (.+?) item submission failed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"backend/app/services/graph_builder.py","lineNumber":517,"sourceCode":"                        batch_id,\n                        expected_item_count,\n                    )\n                    recovered_indexes = {\n                        getattr(item, \"sequence_index\", None)\n                        for item in recovered_items\n                    }\n                    if (\n                        len(recovered_items) == expected_item_count\n                        and recovered_indexes == set(range(expected_item_count))\n                    ):\n                        item_details = recovered_items[i:expected_item_count]\n                    else:\n                        raise RuntimeError(\n                            f\"Zep batch {batch_id} item submission is unconfirmed; \"\n                            \"the draft was not processed or replayed\"\n                        ) from e\n                else:\n                    raise RuntimeError(\n                        f\"Zep batch {batch_id} item submission failed\"\n                    ) from e\n\n            if len(item_details or []) != len(items):\n                recovered_items = self._reconcile_batch_item_count(\n                    batch_id,\n                    expected_item_count,\n                )\n                recovered_indexes = {\n                    getattr(item, \"sequence_index\", None)\n                    for item in recovered_items\n                }\n                if (\n                    len(recovered_items) == expected_item_count\n                    and recovered_indexes == set(range(expected_item_count))\n                ):\n                    item_details = recovered_items[i:expected_item_count]\n                else:","sourceCodeStart":499,"sourceCodeEnd":535,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/services/graph_builder.py#L499-L535","documentation":"RuntimeError in submit_document_batch: client.batch.add failed with an error that is_retryable_zep_error classified as non-retryable (e.g. 400 validation, 401 auth, 404 unknown batch). Since replaying a non-idempotent add against an ambiguous state is unsafe and recovery reconciliation is only attempted for retryable failures, the code fails immediately with the original error as cause.","triggerScenarios":"Adding items to a batch_id that was deleted or already processed (404/409); auth token expired mid-build (401); item payload violates Zep limits (e.g. a chunk >10,000 chars slipping past validation); malformed request after SDK version change (400).","commonSituations":"ZEP_API_KEY rotated or revoked during a long build; the batch was manually deleted in the Zep console mid-run; SDK upgrade changing add-item request shape; chunker regression producing oversized chunks.","solutions":["Read the chained cause exception — it carries the true Zep error code and message.","401/403: refresh ZEP_API_KEY and restart the build; the batch journal allows clean resume.","404/409 on the batch: the batch no longer accepts items — clear project.zep_batch_id/operation_id and start a new batch.","400/validation: fix the payload (re-check chunk sizes/counts with validate_batch_chunks) before resubmitting.","Pin the SDK version if a client upgrade changed the add-item schema."],"exampleFix":"# before\nelse:\n    raise RuntimeError(f\"Zep batch {batch_id} item submission failed\") from e\n\n# after - classify the refusal with the underlying status for faster diagnosis\nelse:\n    status = getattr(getattr(e, 'response', None), 'status_code', None)\n    raise RuntimeError(\n        f\"Zep batch {batch_id} item submission failed\"\n        + (f\" (HTTP {status})\" if status else \"\")\n        + \"; batch may be deleted, processed, or the payload rejected\"\n    ) from e","handlingStrategy":"try-catch","validationCode":"builder.validate_batch_chunks(chunks, batch_size=batch_size)  # catches size/count issues pre-flight\nassert graph_id and project.zep_batch_id, 'batch must exist before adding items'","typeGuard":null,"tryCatchPattern":"try:\n    submission = builder.submit_document_batch(graph_id, chunks, batch_size=bs)\nexcept RuntimeError as e:\n    cause = e.__cause__\n    status = getattr(getattr(cause, 'response', None), 'status_code', None)\n    if status in (401, 403):\n        logger.error('Zep auth failed during item add; check ZEP_API_KEY')\n    elif status in (404, 409):\n        project.zep_batch_id = None  # batch gone; next run starts a new batch\n    raise","preventionTips":["Classify the chained cause's HTTP status before deciding retry vs restart.","Rotate ZEP_API_KEY proactively so long builds do not die mid-run on auth expiry.","Do not delete batches in the Zep console while a build is resumable, or clear the persisted ids if you do.","Re-run validate_batch_chunks before every resume to catch payload regressions."],"tags":["backend","python","zep","batch","non-retryable","api-error"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}