666ghj/MiroFish · error · RuntimeError
Zep batch list cursor did not advance
Error message
Zep batch list cursor did not advance
What it means
RuntimeError in _find_batch_by_operation_id (graph_builder.py): while paginating Zep's batch list to reconcile a possibly-lost batch-create response, the returned next_cursor either equals the current cursor or a previously seen one. The service treats a non-advancing cursor as a protocol violation and aborts instead of looping forever, because continuing would re-scan the same page and could append duplicate matches.
Source
Thrown at backend/app/services/graph_builder.py:299
cursor: int | None = None
seen_cursors: set[int] = set()
while True:
page = call_zep_read_with_retry(
lambda: self.client.batch.list(limit=100, cursor=cursor),
operation_name=f"reconcile batch create {operation_id}",
)
for batch in getattr(page, "batches", None) or []:
metadata = getattr(batch, "metadata", None) or {}
if (
metadata.get("mirofish_operation_id") == operation_id
and metadata.get("graph_id") == graph_id
):
matches.append(batch)
next_cursor = getattr(page, "next_cursor", None)
if next_cursor is None:
break
if next_cursor == cursor or next_cursor in seen_cursors:
raise RuntimeError("Zep batch list cursor did not advance")
seen_cursors.add(next_cursor)
cursor = next_cursor
if len(matches) > 1:
raise RuntimeError(
f"Multiple Zep batches match operation {operation_id}; refusing ambiguity"
)
if matches:
return matches[0]
if attempt < max_attempts:
time.sleep(attempt)
return None
def set_ontology(self, graph_id: str, ontology: Dict[str, Any]):
"""设置图谱本体(公开方法)"""
import warnings
from typing import Optional
from pydantic import FieldView on GitHub (pinned to b5b53acc57)
Solutions
- Retry the operation — transient pagination glitches usually clear; the deterministic operation_id makes a retry of the whole reconcile safe.
- Upgrade (or pin) the Zep client SDK to a version whose list-batch pagination matches this code path.
- Inspect the raw page payloads (log next_cursor per iteration) to confirm whether the server or the client is repeating pages.
- If Zep consistently misbehaves, list all batches non-paginated (if supported) or filter server-side by metadata to avoid cursor logic.
- Check for caching proxies between the backend and Zep Cloud and exclude the batch endpoint.
Example fix
# before
if next_cursor == cursor or next_cursor in seen_cursors:
raise RuntimeError("Zep batch list cursor did not advance")
# after - tolerate one repeat by re-requesting once, then fail with context
if next_cursor == cursor or next_cursor in seen_cursors:
if not retried_this_page:
retried_this_page = True
continue # one fresh request for the same cursor
raise RuntimeError(
f"Zep batch list cursor did not advance (cursor={cursor!r}, "
f"seen={len(seen_cursors)} pages); aborting to avoid an infinite loop"
) Defensive patterns
Strategy: retry
Try / catch
try:
batch = builder._find_batch_by_operation_id(graph_id, operation_id)
except RuntimeError as e:
if 'cursor did not advance' in str(e):
time.sleep(2)
batch = builder._find_batch_by_operation_id(graph_id, operation_id) # one bounded retry
else:
raise Prevention
- Pin the Zep SDK version so pagination semantics match the code.
- Log each next_cursor during reconcile to detect pagination anomalies early.
- Ensure no caching proxy sits in front of api.zep.ai batch-list calls.
- Keep the seen_cursors loop guard intact — never 'fix' this error by removing the cycle check.
When it happens
Trigger: Zep Cloud's batch list endpoint returns the same next_cursor for consecutive pages (server bug or pagination quirk); a middleware/proxy caches the list response so every page looks identical; the page object shape changed so next_cursor parsing yields a stale value.
Common situations: Zep SDK/API version drift changing pagination semantics; large batch histories triggering cursor reuse; flaky network plus an aggressive retry layer replaying the same response.
Related errors
- Graph {graph_id} is in use by active consumer(s): {', '.join
- Persisted Zep batch does not match the current graph input
- ZEP_API_KEY 未配置
- Multiple Zep batches match operation {operation_id}; refusin
- graph_id is required
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/8fee9ca3c23c27b4.
Report an issue: GitHub.