666ghj/MiroFish · error · RuntimeError
Zep graph.add returned no episode UUID
Error message
Zep graph.add returned no episode UUID
What it means
Raised in ZepGraphMemoryUpdater after a successful-looking call to Zep Cloud's graph.add: the returned episode object exposes neither a 'uuid_' nor a 'uuid' attribute, so the updater cannot track the episode for later ingestion polling. Because graph.add is not idempotent, the updater deliberately fails closed instead of retrying — replaying an ambiguous response could duplicate extracted facts in the knowledge graph.
Source
Thrown at backend/app/services/zep_graph_memory_updater.py:524
"last_round": max(a.round_num for a in payload_activities),
"agent_ids": ",".join(
str(value)
for value in sorted({a.agent_id for a in payload_activities})
),
"action_types": ",".join(
value
for value in sorted({a.action_type for a in payload_activities})
if value
) or "unknown",
},
)
episode_uuid = (
getattr(episode, "uuid_", None)
or getattr(episode, "uuid", None)
)
if not episode_uuid:
raise RuntimeError("Zep graph.add returned no episode UUID")
self._pending_episode_uuids.append(str(episode_uuid))
self._total_sent += 1
self._total_items_sent += len(payload_activities)
display_name = self._get_platform_display_name(platform)
logger.info(f"成功批量发送 {len(payload_activities)} 条{display_name}活动到图谱 {self.graph_id}")
logger.debug(f"批量内容预览: {combined_text[:200]}...")
except Exception as e:
# graph.add has no idempotency key. Replaying an ambiguous
# response can duplicate extracted facts, so fail closed and
# surface the incomplete batch to SimulationRunner.
logger.error(f"批量发送到Zep失败,未自动重放非幂等写入: {e}")
self._failed_count += 1
self._failed_batches.append({
"platform": platform,
"activities": payload_activities,
"error": str(e),
})View on GitHub (pinned to b5b53acc57)
Solutions
- Log the raw episode object (repr/dir) at the failure site to see which fields Zep actually returned
- Pin the zep-cloud SDK to a tested version and check its changelog for episode response changes
- If the field was renamed, extend the getattr chain in zep_graph_memory_updater.py:519-522 to include the new attribute name
- Do NOT add automatic retry around graph.add — it is non-idempotent; a retry can duplicate extracted facts
- Verify the graph_id exists and the API key has write permission on that graph
Example fix
# before
episode_uuid = (
getattr(episode, "uuid_", None)
or getattr(episode, "uuid", None)
)
if not episode_uuid:
raise RuntimeError("Zep graph.add returned no episode UUID")
# after
episode_uuid = (
getattr(episode, "uuid_", None)
or getattr(episode, "uuid", None)
)
if not episode_uuid:
logger.error("Unexpected graph.add response: %r", episode)
raise RuntimeError("Zep graph.add returned no episode UUID") Defensive patterns
Strategy: try-catch
Try / catch
try:
episode = client.graph.add(...)
except RuntimeError:
# fail closed: do NOT replay graph.add (non-idempotent); surface to runner
raise Prevention
- Pin the zep-cloud SDK version and test after upgrades
- Log the raw episode object whenever the UUID is missing to catch schema drift early
- Never wrap graph.add in automatic retries without an idempotency key
When it happens
Trigger: Calling client.graph.add(...) (batch of platform activities) where the server response body omits the episode UUID field, or a Zep Cloud SDK version whose episode model names the field differently than uuid_/uuid. Also possible if the API silently changed its response schema or returned a degraded/error object that still parsed.
Common situations: Zep Cloud API/SDK version drift (response schema change), a misconfigured graph_id causing a partial response, or a proxy/gateway stripping response fields. Typically surfaces mid-simulation while flushing buffered activities.
Related errors
- 启用图谱记忆更新时必须提供 graph_id
- Zep图谱更新器初始化失败: {e}
- 模拟仍在停止中,图谱写入未在 {wait_timeout:.0f}s 内完成
- Zep图谱写入未完整完成: {error}
- ZEP_API_KEY 未配置
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/5d7127d5244cb861.
Report an issue: GitHub.