Client timeout + retry can duplicate memcells for identical session/messages payload
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
调研方向
Start by tracing /api/v1/memory/add and /api/v1/memory/flush, then inspect how the buffer merge path consumes messages and creates rows in the SQLite memcell table. Decide how retries should be identified and handled, including what happens when a key is reused with a different payload. Done means a retry cannot create duplicate memcells or downstream Markdown and search results, and the behavior is covered by tests.
由索引模型根据 Issue 内容生成。
描述
Summary
When a client times out on /api/v1/memory/add or /api/v1/memory/flush, the server may continue processing in the background. If the client then retries the same session_id with the identical messages payload, EverOS can create duplicate memcell rows with the same message_ids_json but different memcell_id values.
Those duplicate memcells can later propagate into Markdown and search results.
Environment
- EverOS version: 1.0.0
- Runtime: Linux container
- Memorize mode:
chat - Memory root: isolated test memory root
- Sample data: synthetic text only
No real user memory was used.
Why this matters
Clients cannot safely treat timeout as failure. A timed-out request may still generate memcells, Markdown files, cascade updates, and searchable rows. If the client blindly retries the same payload, the memory store can be polluted with duplicate memories.
This is especially risky for agent memory integrations, where callers often retry on HTTP timeout.
Reproduction Outline
Use an isolated memory root and synthetic messages.
- Start EverOS server in
chatmode. - Send
/api/v1/memory/addwith a short client timeout. - Send
/api/v1/memory/flushwith a short client timeout. - Without auditing backend state, retry the same
/addpayload:- same
app_id - same
project_id - same
session_id - same
messages - same timestamps
- same
- Retry
/flush. - Inspect SQLite
memcell. - Wait for background extraction / cascade to finish.
- Inspect Markdown and search results.
Synthetic Payload Shape
Example payload shape:
{
"session_id": "retry_probe_001",
"app_id": "test_app",
"project_id": "retry_audit",
"messages": [
{
"sender_id": "test_user",
"sender_name": "Test User",
"role": "user",
"timestamp": 1780870000000,
"content": "Remember exactly: retry-token-mu equals audit-mu-772."
},
{
"sender_id": "test_assistant",
"sender_name": "Test Assistant",
"role": "assistant",
"timestamp": 1780870000500,
"content": "Acknowledged. I will preserve the exact retry audit token."
}
]
}
Observed Behavior
After retrying the same payload, SQLite contained two memcell rows for the same session.
Both rows had the same message_ids_json, but different memcell_id values.
Example observed shape:
memcell_id: mc_<first>
message_ids_json:
["m_retry_probe_001_1780870000000_000", "m_retry_probe_001_1780870000500_001"]
memcell_id: mc_<second>
message_ids_json:
["m_retry_probe_001_1780870000000_000", "m_retry_probe_001_1780870000500_001"]
After background processing completed:
- Markdown contained repeated references to the same synthetic marker.
- Search returned duplicate episode results for the same synthetic marker.
Expected Behavior
EverOS should provide retry-safe behavior for timed-out clients.
Possible acceptable fixes:
- Support an
idempotency_keyorclient_request_idon/add. - Expose request/session processing status so clients can audit before retrying.
- Prevent duplicate memcell creation for the same
app_id,project_id,session_id,track, andmessage_ids_json. - Document safe retry behavior for
/addand/flush.
Current Code Observation
The input message IDs appear deterministic for the same session_id, timestamp, and message index.
However, memcell_id is minted independently for each boundary result. The memcell table uses memcell_id as primary key and does not appear to enforce uniqueness on:
app_id + project_id + session_id + track + message_ids_json
The buffer merge path deduplicates by message_id, but once messages have been consumed into a memcell and the buffer is cleared, replaying the same payload can create a new memcell.
Suggested Direction
The safest contract would be API-level idempotency:
- Client supplies an
idempotency_key. - EverOS stores key + payload hash + processing status + result.
- Retrying the same key returns the original result or current processing state.
- Same key with different payload returns a conflict error.
A lower-level safety net would be to prevent duplicate memcells for the same scoped message_ids_json, but that alone may not fully solve HTTP retry semantics.
- 主要语言
- Python
- 星标
- 13.3k
- 派生
- 926
- 平均合并
- 17 小时 8 分钟
- 30 天内合并 PR
- 32
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
EverMind-AI/EverOS 的其他 Issue
-
难度 2/5 半天 新手友好度 62/100
EverMind-AI/EverOS#414 ·
维护者通常 1 天内回复
-
[Offer] Free independent recomputation of your published memory benchmarks (assayed-tier upgrade)未关闭
难度 4/5 1-2 天 新手友好度 3/100
EverMind-AI/EverOS#504 ·
维护者通常 1 天内回复
-
enhancement
难度 4/5 3-5 天 新手友好度 35/100
EverMind-AI/EverOS#501 ·
维护者通常 1 天内回复
-
难度 3/5 1-2 天 新手友好度 55/100
EverMind-AI/EverOS#498 ·
维护者通常 1 天内回复
-
难度 3/5 1-2 天 新手友好度 35/100
EverMind-AI/EverOS#485 ·
维护者通常 1 天内回复
查看 EverMind-AI/EverOS 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 77/100
lidofinance/diffyscan#239 ·
维护者通常 1 天内回复
-
area: tools documentation good first issue ready for a contributor
难度 2/5 1-3 小时 新手友好度 82/100
eyalgolan/statecraft-israel#873 · 1 条评论 ·
维护者通常 1 天内回复
-
GET rooms API returns 500 due to nonexistent Room.is_active attribute可能已有人在做 @Mars-60 今天认领。 未关闭bug
难度 2/5 1-3 小时 新手友好度 84/100
维护者通常 1 天内回复
-
enhancement
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 5 天内回复
-
Harmony OPeNDAP SubSetter (HOSS) Geographic production rssmif16d 7 XYZ_PROV
难度 2/5 1-3 小时 新手友好度 62/100
nasa/harmony-autotester#341 ·