666ghj/MiroFish · error · RuntimeError
Zep batch {submission.batch_id} contains {len(items)} items,
Error message
Zep batch {submission.batch_id} contains {len(items)} items, expected {submission.item_count} What it means
Raised by GraphBuilder._wait_for_batch when the batch status is 'succeeded' but paginating all items via _list_batch_items returns a count different from submission.item_count. It guards against silent item loss: a succeeded batch must yield exactly the number of items that were submitted, otherwise downstream UUID ordering would be wrong. A mismatch means pagination dropped/duplicated pages or the submission bookkeeping miscounted.
Source
Thrown at backend/app/services/graph_builder.py:685
)
if status in terminal_states:
break
time.sleep(3)
items = self._list_batch_items(submission.batch_id)
if status != "succeeded":
failed_items = [
item for item in items
if getattr(item, "status", None) not in {"succeeded", "skipped"}
]
first_error = getattr(failed_items[0], "error", None) if failed_items else None
raise RuntimeError(
f"Zep batch {submission.batch_id} ended as {status}; "
f"failed_items={len(failed_items)}; first_error={first_error}"
)
if len(items) != submission.item_count:
raise RuntimeError(
f"Zep batch {submission.batch_id} contains {len(items)} items, "
f"expected {submission.item_count}"
)
ordered_items = sorted(
items,
key=lambda item: getattr(item, "sequence_index", 0) or 0,
)
episode_uuids: List[str] = []
for item in ordered_items:
item_status = getattr(item, "status", None)
episode_uuid = getattr(item, "episode_uuid", None)
source_uuid = getattr(item, "source_uuid", None)
if item_status != "succeeded" or not episode_uuid:
raise RuntimeError(
f"Zep batch {submission.batch_id} returned an incomplete item"
)
if source_uuid and source_uuid != episode_uuid:View on GitHub (pinned to b5b53acc57)
Solutions
- Re-list the batch items after a short delay — propagation lag right after 'succeeded' often resolves the count.
- Verify how item_count is computed where BatchSubmission is built; it must equal the exact number of items sent in the add call(s).
- Compare counts per page of list_items to spot skipped/duplicated cursors; if cursors misbehave, see error 21's guidance (SDK version, retry).
- If the count is consistently wrong on Zep's side, escalate with batch_id — silent item loss is a service defect.
Example fix
# before
items = self._list_batch_items(submission.batch_id)
# after (allow a short propagation window)
items = self._list_batch_items(submission.batch_id)
for _ in range(3):
if len(items) == submission.item_count:
break
time.sleep(5)
items = self._list_batch_items(submission.batch_id) Defensive patterns
Strategy: retry
Try / catch
try:
builder._wait_for_batch(submission)
except RuntimeError as e:
if 'items, expected' in str(e):
time.sleep(10)
items = builder._list_batch_items(submission.batch_id) # re-read once for propagation lag
if len(items) != submission.item_count:
raise
else:
raise Prevention
- Derive BatchSubmission.item_count from the same list passed to the add call — never a separate counter.
- When retrying an add after ambiguity, reconcile the actual item count server-side before proceeding.
- Keep pagination cursor logs to audit for skipped pages.
When it happens
Trigger: Cursor pagination in _list_batch_items skipping or repeating pages for batches over 100 items; items still propagating when listed immediately after 'succeeded' (eventual consistency); submitting items in multiple add calls but recording the wrong item_count in BatchSubmission.
Common situations: Large batches right at the moment of completion; Zep cursor anomalies (also visible as error 21); code paths that add items in a loop but construct BatchSubmission with a stale count; retries of the add call that double-append items without updating item_count.
Related errors
- Zep batch {batch_id} item cursor did not advance
- Zep batch {submission.batch_id} did not finish within {timeo
- Zep batch {submission.batch_id} ended as {status}; failed_it
- Zep batch {submission.batch_id} returned an incomplete item
- Zep batch {submission.batch_id} returned mismatched episode
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/053c58dd34c02833.
Report an issue: GitHub.