Bug 报告:EverOS cascade worker 因 LanceDB Spill IO 错误无法索引记忆
一句话
EverOS 记忆索引后台(cascade worker)在把 episode 写入 LanceDB 时,命中 LanceDB Rust 侧的 Spill has sent an error IO 错误,导致最近的记忆条目被标记为 failed 且 retryable=False,永久进不了向量/BM25 索引 → recall 对新记忆静默失效。不影响对话本身,只影响长期记忆的沉淀与召回。
环境
- everos: 1.1.2
- lancedb: 0.34.0(pyarrow 25.0.0;未单独装 pylance/lance,用 lancedb 自带的 Rust 库)
- Python 3.12,运行于 uv-tool 环境(raven editable 安装)
- OS: macOS (Darwin 25.3.0),Apple Silicon (arm64)
- 索引位置(raven 专用实例):
~/.everos/raven/.index/
- 磁盘:未爆盘(剩余 ~299G,
~/.everos 仅 1.4G)——排除空间不足
现象 / 影响
~/.everos/raven/.index/sqlite/system.db 的 md_change_state 表:
status 分布: done=25, failed=2
failed 条目:
default_app/default_project/users/default/episodes/episode-2026-07-12.md
default_app/default_project/users/default/episodes/episode-2026-07-13.md
(二者 error 相同,见下;retryable=0 / retry_count=0)
- 最近两天(7-12、7-13)的 episode 没能写进索引,且被标为 retryable=False,不会自动重试 → 除非人工 reprocess,否则这两段记忆永久搜不到。
- 观察到该错误在被标记为 failed 前经历了大量重试崩溃(tui.log 中
Spill has sent an error 出现 200+ 次)。
完整错误
RuntimeError: lance error: LanceError(IO): Execution error: Spill has sent an error,
/rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/task/poll.rs:291:44
- 这是 LanceDB Rust 侧在一次异步 spill-to-disk(
poll.rs)时抛出的 IO 错误,冒泡成 Python RuntimeError。
- 相关上下文帧里出现
on_bad_vectors = 'error'(LanceDB add 的参数),说明发生在写入/建索引路径。
代码定位(EverOS 侧调用链)
everos/memory/cascade/worker.py — worker 循环调用 handler.handle_added_or_modified(row.md_path);捕获 RecoverableError 重试,最终 mark_failed(retryable=False)(约 300-330 行 except RecoverableError 段)。
everos/memory/cascade/handlers/base.py — handler 用 embedding 生成向量后写 LanceDB。
- 写入/建索引落点(触发 lance 的地方):
everos/core/persistence/lancedb/repository.py:145 await table.add(...)
- 同文件
:168 merge_insert(by)、:176 optimize(...)
everos/core/persistence/lancedb/base.py:142 await table.create_index(..., config=FTS(...))(BM25 全文索引)
- lance 的
Spill 错误发生在上述某个 LanceDB 异步操作内部(Rust 层)。
疑似根因(待负责人确认)
Spill has sent an error 是 LanceDB 在内存不足时把中间结果 spill 到磁盘的执行路径报错,常见诱因:
- lancedb 0.34.0 的已知/回归 bug(spill executor 在某些数据规模或并发下崩);
- FTS
create_index 或 add/merge_insert 在该数据量下触发 spill;
- 也可能与之前记录过的 lance 自动 optimize/encoding bug 同源。
(本人无法在 EverOS 仓库改代码,故整理证据交由负责人定位。)
复现要点
- 用 raven TUI 正常对话,产生新的 episode md(落
~/.everos/raven/.index)。
- cascade worker 扫到该 md → embed → 写 LanceDB → 命中上述 Spill 错误。
- 查
system.db 的 md_change_state,可见对应 episode status=failed。
建议排查方向
- 单独跑一次对 failed episode 的 handler,开 lancedb / lance 的 debug/backtrace(
RUST_BACKTRACE=1),拿到 lance 内部完整栈,确认是 add 还是 create_index(FTS) 触发 spill。
- 试 bump / 回退 lancedb 版本(0.34.0 → 相邻版本)看是否为版本回归。
- 评估该数据量是否真需要 spill;若是 lance bug,考虑限制批量大小 / 关闭相关优化 / 给 worker 加降级路径(写失败时至少保留可 flat-scan 的回退,避免 recall 整段丢失)。
- 对已
retryable=False 的历史条目,提供一个人工 reprocess / 重置 status 的入口,把卡住的记忆补进索引。
不是这个 bug 的东西(避免混淆)
Bug 报告:EverOS cascade worker 因 LanceDB
SpillIO 错误无法索引记忆一句话
EverOS 记忆索引后台(cascade worker)在把 episode 写入 LanceDB 时,命中 LanceDB Rust 侧的
Spill has sent an errorIO 错误,导致最近的记忆条目被标记为 failed 且 retryable=False,永久进不了向量/BM25 索引 → recall 对新记忆静默失效。不影响对话本身,只影响长期记忆的沉淀与召回。环境
~/.everos/raven/.index/~/.everos仅 1.4G)——排除空间不足现象 / 影响
~/.everos/raven/.index/sqlite/system.db的md_change_state表:Spill has sent an error出现 200+ 次)。完整错误
poll.rs)时抛出的 IO 错误,冒泡成 PythonRuntimeError。on_bad_vectors = 'error'(LanceDBadd的参数),说明发生在写入/建索引路径。代码定位(EverOS 侧调用链)
everos/memory/cascade/worker.py— worker 循环调用handler.handle_added_or_modified(row.md_path);捕获RecoverableError重试,最终mark_failed(retryable=False)(约 300-330 行except RecoverableError段)。everos/memory/cascade/handlers/base.py— handler 用 embedding 生成向量后写 LanceDB。everos/core/persistence/lancedb/repository.py:145await table.add(...):168merge_insert(by)、:176optimize(...)everos/core/persistence/lancedb/base.py:142await table.create_index(..., config=FTS(...))(BM25 全文索引)Spill错误发生在上述某个 LanceDB 异步操作内部(Rust 层)。疑似根因(待负责人确认)
Spill has sent an error是 LanceDB 在内存不足时把中间结果 spill 到磁盘的执行路径报错,常见诱因:create_index或add/merge_insert在该数据量下触发 spill;(本人无法在 EverOS 仓库改代码,故整理证据交由负责人定位。)
复现要点
~/.everos/raven/.index)。system.db的md_change_state,可见对应 episodestatus=failed。建议排查方向
RUST_BACKTRACE=1),拿到 lance 内部完整栈,确认是add还是create_index(FTS)触发 spill。retryable=False的历史条目,提供一个人工 reprocess / 重置 status 的入口,把卡住的记忆补进索引。不是这个 bug 的东西(避免混淆)
another OfflineEngine instance already holds ome.db.lock:只是同时跑了两个 raven 实例抢锁,属预期并发保护,非本 bug。No module named 'orjson'导致的turn_failed:是 raven 侧的依赖缺失(另一个独立问题,已在 raven 提 PR docs: update README with OpenClaw plugin release and image link #116 修复),与 EverOS 无关。