{"record":{"id":"6ebe233fc512b74f","repo":"666ghj/MiroFish","slug":"persisted-zep-batch-does-not-match-the-current-gra","errorCode":null,"errorMessage":"Persisted Zep batch does not match the current graph input","messagePattern":"Persisted Zep batch does not match the current graph input","errorType":"exception","errorClass":"RuntimeError","httpStatus":500,"severity":"error","filePath":"backend/app/api/graph.py","lineNumber":683,"sourceCode":"                # 分块\n                task_manager.update_task(\n                    task_id,\n                    message=t('progress.textChunking'),\n                    progress=5\n                )\n                chunks = TextProcessor.split_text(\n                    text, \n                    chunk_size=chunk_size, \n                    overlap=chunk_overlap\n                )\n                builder.validate_batch_chunks(chunks, batch_size=350)\n                total_chunks = len(chunks)\n                \n                if resume_existing_batch:\n                    graph_id = project.graph_id\n                    operation_id = builder.build_operation_id(graph_id, chunks)\n                    if operation_id != project.zep_batch_operation_id:\n                        raise RuntimeError(\n                            \"Persisted Zep batch does not match the current graph input\"\n                        )\n                    submission = BatchSubmission(\n                        batch_id=project.zep_batch_id,\n                        operation_id=operation_id,\n                        episode_uuids=[],\n                        item_count=total_chunks,\n                    )\n                    task_manager.update_task(\n                        task_id,\n                        message=t('progress.waitingZepProcess'),\n                        progress=55,\n                    )\n                else:\n                    # 创建图谱\n                    task_manager.update_task(\n                        task_id,\n                        message=t('progress.creatingZepGraph'),","sourceCodeStart":665,"sourceCodeEnd":701,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/api/graph.py#L665-L701","documentation":"RuntimeError in the graph-build resume path (backend/app/api/graph.py): when resuming an existing Zep batch the service recomputes operation_id = build_operation_id(graph_id, chunks) — a deterministic hash of graph identity plus chunk content — and compares it to project.zep_batch_operation_id persisted when the batch was created. A mismatch means the text input or chunking parameters changed between the original submission and the resume attempt, so the persisted batch belongs to different content and must not be resumed.","triggerScenarios":"Resuming a build with resume_existing_batch=true after: the source document was re-uploaded or edited; chunk_size/chunk_overlap changed in the request; the project's text preprocessing produced different chunks (TextProcessor behavior change between versions); or graph_id changed but the old zep_batch_operation_id row survived.","commonSituations":"User pauses a long build, edits the document, and hits resume; deployment upgrades the text splitter mid-batch; two tabs building the same project with different chunk settings overwrite each other's state.","solutions":["Resume with the exact same document and chunk_size/chunk_overlap values used when the batch started.","If the input intentionally changed, do not resume: start a fresh batch (clear zep_batch_id/zep_batch_operation_id on the project) so a new operation is created.","Persist chunk_size/chunk_overlap alongside zep_batch_operation_id at submission time and reuse them on resume instead of trusting request parameters.","If TextProcessor.split_text changed across versions, restart the build from scratch rather than resuming pre-upgrade batches."],"exampleFix":"# before\nif resume_existing_batch:\n    graph_id = project.graph_id\n    operation_id = builder.build_operation_id(graph_id, chunks)\n    if operation_id != project.zep_batch_operation_id:\n        raise RuntimeError(\"Persisted Zep batch does not match the current graph input\")\n\n# after - self-heal by abandoning the stale batch instead of hard-failing\nif resume_existing_batch:\n    operation_id = builder.build_operation_id(graph_id, chunks)\n    if operation_id != project.zep_batch_operation_id:\n        logger.warning(\"Stale batch %s for project %s; starting a new batch\", project.zep_batch_id, project.id)\n        resume_existing_batch = False  # fall through to fresh submission\n        project.zep_batch_id = None\n        project.zep_batch_operation_id = None","handlingStrategy":"validation","validationCode":"if resume_existing_batch:\n    stored = project.zep_batch_params  # {chunk_size, chunk_overlap, text_hash} persisted at submission\n    if stored and (stored['chunk_size'] != chunk_size or stored['chunk_overlap'] != chunk_overlap):\n        resume_existing_batch = False  # input changed; start a new batch","typeGuard":null,"tryCatchPattern":"try:\n    _resume_or_submit(resume_existing_batch)\nexcept RuntimeError as e:\n    if 'does not match the current graph input' in str(e):\n        project.zep_batch_id = None\n        project.zep_batch_operation_id = None\n        _resume_or_submit(resume_existing_batch=False)\n    else:\n        raise","preventionTips":["Persist chunk_size/chunk_overlap/text hash next to zep_batch_operation_id at submission and reuse them verbatim on resume.","Lock the project against document edits while a build is in flight or resumable.","Clear persisted batch identity whenever the source document or splitter version changes.","Treat this error as a signal to restart, never to force-resume."],"tags":["backend","python","zep","batch","resume","data-integrity"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}