666ghj/MiroFish · warning · RuntimeError

Zep graph updater is not running

Error message

Zep graph updater is not running

What it means

add_activity() guards the accepting state: under _acceptance_lock it checks self._running, and once stop() has flipped _running to False it rejects further activities with RuntimeError('Zep graph updater is not running'). DO_NOTHING activities are skipped before this check (just counted), so the error only fires for real actions enqueued after shutdown began.

Source

Thrown at backend/app/services/zep_graph_memory_updater.py:378

        - LIKE_POST/DISLIKE_POST(点赞/踩帖子)
        - REPOST(转发)
        - FOLLOW(关注)
        - MUTE(屏蔽)
        - LIKE_COMMENT/DISLIKE_COMMENT(点赞/踩评论)
        
        action_args中会包含完整的上下文信息(如帖子原文、用户名等)。
        
        Args:
            activity: Agent活动记录
        """
        # 跳过DO_NOTHING类型的活动
        if activity.action_type == "DO_NOTHING":
            self._skipped_count += 1
            return

        with self._acceptance_lock:
            if not self._running:
                raise RuntimeError("Zep graph updater is not running")
            self._activity_queue.put(activity)
            self._total_activities += 1
        logger.debug(f"添加活动到Zep队列: {activity.agent_name} - {activity.action_type}")
    
    def add_activity_from_dict(self, data: Dict[str, Any], platform: str):
        """
        从字典数据添加活动
        
        Args:
            data: 从actions.jsonl解析的字典数据
            platform: 平台名称 (twitter/reddit)
        """
        # 跳过事件类型的条目
        if "event_type" in data:
            return
        if data.get("success") is False:
            self._skipped_count += 1
            return

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Make producers stop before calling stop(): signal the action source, join it, then stop the updater.
  2. Catch this RuntimeError in the producer as an expected shutdown signal and exit the feed loop cleanly.
  3. Never reuse an updater after stop(); construct a new one (new graph_id) for a subsequent run.

Example fix

# before
def on_action(activity):
    updater.add_activity(activity)  # RuntimeError once stop() begins

# after
def on_action(activity):
    try:
        updater.add_activity(activity)
    except RuntimeError:
        logger.info("updater closed; dropping activity feed")
        stop_event.set()  # unwind producers before stop()
Defensive patterns

Strategy: try-catch

Try / catch

try:
    updater.add_activity(activity)
except RuntimeError as e:
    if "not running" in str(e):
        stop_feed.set()  # expected during shutdown; unwind producer
        return
    raise

Prevention

When it happens

Trigger: A producer thread (action-file tailer or platform runner) calling add_activity after stop() started — the classic race the acceptance lock exists to close; or a caller reusing an updater instance after stop() completed.

Common situations: Simulation actions still being parsed/fed while the runner is finalizing; retry logic that keeps pumping activities after a stop request; tests that stop the updater then feed more events.

Related errors


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