666ghj/MiroFish · error · RuntimeError

Zep batch {batch_id} acknowledged {len(item_details or [])}

Error message

Zep batch {batch_id} acknowledged {len(item_details or [])} of {len(items)} items

What it means

RuntimeError in submit_document_batch: after adding a group of items, the count of acknowledged item_details does not match len(items), so the code reconciles via _reconcile_batch_item_count and re-checks sequence_index completeness. If the reconciled list still is not exactly expected_item_count items with indexes range(expected_item_count), Zep acknowledged fewer items than were submitted and the mismatch is unrecoverable — proceeding would silently drop graph episodes.

Source

Thrown at backend/app/services/graph_builder.py:536

                        f"Zep batch {batch_id} item submission failed"
                    ) from e

            if len(item_details or []) != len(items):
                recovered_items = self._reconcile_batch_item_count(
                    batch_id,
                    expected_item_count,
                )
                recovered_indexes = {
                    getattr(item, "sequence_index", None)
                    for item in recovered_items
                }
                if (
                    len(recovered_items) == expected_item_count
                    and recovered_indexes == set(range(expected_item_count))
                ):
                    item_details = recovered_items[i:expected_item_count]
                else:
                    raise RuntimeError(
                        f"Zep batch {batch_id} acknowledged {len(item_details or [])} "
                        f"of {len(items)} items"
                    )
            for item in item_details:
                episode_uuid = getattr(item, "episode_uuid", None)
                if episode_uuid:
                    episode_uuids.append(episode_uuid)

        try:
            self.client.batch.process(batch_id=batch_id)
        except Exception as error:
            # A process response can be lost after the server accepted it.
            # Reconcile with a safe GET instead of issuing a second POST.
            summary = call_zep_read_with_retry(
                lambda: self.client.batch.get(batch_id=batch_id),
                operation_name=f"reconcile batch {batch_id}",
            )
            if getattr(summary, "status", None) in {None, "draft"}:

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Retry via the resume flow once backend/Zep recovers — the persisted batch identity supports it.
  2. Inspect the batch items in the Zep console and identify which sequence indexes are missing; if unrecoverable, delete the draft batch and rebuild.
  3. Ensure only one worker processes a given operation at a time (per-project submission lock) so counts are not skewed by concurrency.
  4. Lower batch_size to reduce per-request item counts if truncation recurs.
  5. Report to Zep if add consistently acknowledges fewer items than sent with a 2xx.

Example fix

# before
else:
    raise RuntimeError(
        f"Zep batch {batch_id} acknowledged {len(item_details or [])} of {len(items)} items"
    )

# after - name the missing indexes so operators can repair precisely
else:
    acked = {getattr(it, "sequence_index", None) for it in (item_details or [])}
    missing = sorted(set(range(expected_item_count)) - acked)
    raise RuntimeError(
        f"Zep batch {batch_id} acknowledged {len(item_details or [])} of {len(items)} items "
        f"(missing sequence indexes: {missing[:20]}{'...' if len(missing) > 20 else ''})"
    )
Defensive patterns

Strategy: validation

Validate before calling

expected = len(items)
recovered = builder._reconcile_batch_item_count(batch_id, expected)
indexes = {getattr(it, 'sequence_index', None) for it in recovered}
if not (len(recovered) == expected and indexes == set(range(expected))):
    raise RuntimeError(f'Batch {batch_id} incomplete; missing {sorted(set(range(expected)) - indexes)}')

Try / catch

try:
    submission = builder.submit_document_batch(graph_id, chunks, batch_size=bs)
except RuntimeError as e:
    if 'acknowledged' in str(e) and 'of' in str(e):
        # item set is provably incomplete; delete the draft batch and rebuild rather than resume
        logger.error('Incomplete batch acknowledgment: %s', str(e))
        raise
    raise

Prevention

When it happens

Trigger: batch.add returns item_details for only part of the submitted group (server truncation or partial acceptance); the reconcile listing shows missing sequence indexes, meaning some chunks never landed; concurrent item additions to the same batch from another process skewing counts.

Common situations: Large batch groups near the 350-item limit under load; Zep Cloud eventually-consistent listing returning partial item sets; two workers resuming the same batch simultaneously.

Related errors


AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14). Data as JSON: /api/errors/16c6aad4bf509728. Report an issue: GitHub.