666ghj/MiroFish · error · AssertionError

unexpected MiroFish updater stats: {updater_stats}

Error message

unexpected MiroFish updater stats: {updater_stats}

What it means

An AssertionError in the validation script after feeding the MiroFish ZepUpdater exactly the 5 activities from _activities(): it requires updater_stats["items_sent"] == 5 and updater_stats["pending_episode_count"] == 0 (checked via updater.get_stats() after add_activity x5 then stop()). Any other numbers mean the updater dropped, rejected, or left activities unprocessed — e.g. an add_activity raced stop(), or a send to Zep failed and was swallowed. The f-string interpolates the actual stats dict.

Source

Thrown at backend/scripts/validate_zep_cloud_integration.py:605

        ]
        result["temporal_update_episode_uuids"] = update_episode_uuids
        print(f"[zep-deep] temporal updates processed={len(update_episode_uuids)}", flush=True)

        updater = ZepGraphMemoryUpdater(
            graph_id=graph_id,
            api_key=api_key,
            simulation_id=f"zep-deep-{stamp}",
        )
        updater_started = True
        updater.start()
        for activity in _activities():
            updater.add_activity(activity)
        updater_stop_attempted = True
        updater.stop()
        updater_drained = True
        updater_stats = updater.get_stats()
        if updater_stats["items_sent"] != 5 or updater_stats["pending_episode_count"] != 0:
            raise AssertionError(f"unexpected MiroFish updater stats: {updater_stats}")
        result["mirofish_updater"] = updater_stats
        print("[zep-deep] MiroFish updater processed 5 mock activities", flush=True)

        final_nodes = fetch_all_nodes(client, graph_id, page_size=2)
        final_edges = fetch_all_edges(client, graph_id, page_size=2)
        final_names = {_uuid(node): node.name for node in final_nodes}
        invalidated = [edge for edge in final_edges if edge.invalid_at]
        expired = [edge for edge in final_edges if edge.expired_at]

        edge_search = client.graph.search(
            graph_id=graph_id,
            query="澜舟科技当前首席执行官、当前总部以及与海岳能源的当前合作关系是什么?",
            scope="edges",
            reranker="cross_encoder",
            limit=20,
        )
        node_search = client.graph.search(
            graph_id=graph_id,

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Read the stats dict in the failure message: items_sent < 5 points to dropped/rejected activities; pending_episode_count > 0 points to an incomplete drain on stop().
  2. Check the updater's logs for swallowed Zep send errors and fix the underlying cause (auth, rate limits) before rerunning.
  3. Reconcile the mock AgentActivity fields in _activities() with the updater's current expected schema.
  4. Rerun once — transient rate limiting during stop() can leave pending episodes.
Defensive patterns

Strategy: try-catch

Validate before calling

def updater_stats_look_correct(stats: dict) -> bool:
    return stats.get("items_sent") == 5 and stats.get("pending_episode_count") == 0

Try / catch

try:
    assert updater_stats_look_correct(updater.get_stats())
except AssertionError:
    stats = updater.get_stats()
    if stats["pending_episode_count"] > 0:
        updater.stop()  # one more drain attempt
        stats = updater.get_stats()
    if not updater_stats_look_correct(stats):
        raise

Prevention

When it happens

Trigger: An activity rejected by the updater's validator (items_sent < 5), stop() returning before the queue fully drains (pending_episode_count > 0), or Zep send errors (auth, rate limit) swallowed by the updater's drain logic.

Common situations: AgentActivity schema drift between _activities() and the updater's expectations; transient Zep Cloud rate limiting during the drain; a bug in the updater's stop path leaving pending episodes.

Related errors


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