666ghj/MiroFish · error · RuntimeError

Zep batch {submission.batch_id} returned mismatched episode

Error message

Zep batch {submission.batch_id} returned mismatched episode UUIDs

What it means

Raised by GraphBuilder._wait_for_batch during per-item validation: for a succeeded item that has a source_uuid, that source_uuid must equal the item's episode_uuid. Zep echoes back the client-supplied source UUID; a mismatch means the server re-associated the item with a different episode than the one the client declared (e.g. dedup merged it into an existing episode), which would corrupt the builder's UUID bookkeeping.

Source

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

                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:
                raise RuntimeError(
                    f"Zep batch {submission.batch_id} returned mismatched episode UUIDs"
                )
            episode_uuids.append(episode_uuid)

        if progress_callback:
            progress_callback(
                t(
                    'progress.processingComplete',
                    completed=len(episode_uuids),
                    total=submission.item_count,
                ),
                1.0,
            )
        return episode_uuids
    
    def _wait_for_episodes(
        self,
        episode_uuids: List[str],

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Use a fresh graph (new graph_id) for a full rebuild instead of re-ingesting into the existing one.
  2. Regenerate unique source_uuid values (e.g. uuid4-derived, content-hash + run-id) for every retry so dedup cannot merge across runs.
  3. Before resubmitting, search the graph (client.graph.episode/search) for the source_uuid to check whether it already exists.
  4. If Zep should never merge, review whether your plan/config enables dedup and disable it for this workflow.

Example fix

# before
source_uuid = content_hash  # stable across runs -> dedup merges
# after
import uuid
source_uuid = f'{run_id}:{content_hash}'  # unique per run
Defensive patterns

Strategy: validation

Validate before calling

def make_source_uuid(run_id: str, content_hash: str) -> str:
    return f'{run_id}:{content_hash}'  # unique per ingestion run, dedup-proof

Try / catch

try:
    uuids = builder._wait_for_batch(submission)
except RuntimeError as e:
    if 'mismatched episode UUIDs' in str(e):
        # episodes were deduped onto an existing graph; rebuild into a fresh graph_id
        raise RuntimeError('re-ingest into a new graph or regenerate source UUIDs') from e
    raise

Prevention

When it happens

Trigger: Submitting items with explicit source_uuid values that collide with already-ingested episodes in the same graph, so Zep deduplicates/merges them into an existing episode and returns a different episode_uuid; or re-running ingestion of the same content into the same graph-id combination twice.

Common situations: Rebuilding a graph without a new graph-id, so previous episodes exist and Zep dedupes new items onto them; retrying a partially failed ingestion run with the same source UUIDs; switching a project between shared and per-project graphs while reusing source UUIDs.

Related errors


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