Skip to content

cascade worker fails to index episodes: LanceDB Spill has sent an error (IO) #337

Description

@arelchan

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.dbmd_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 侧调用链)

  1. everos/memory/cascade/worker.py — worker 循环调用 handler.handle_added_or_modified(row.md_path);捕获 RecoverableError 重试,最终 mark_failed(retryable=False)(约 300-330 行 except RecoverableError 段)。
  2. everos/memory/cascade/handlers/base.py — handler 用 embedding 生成向量后写 LanceDB。
  3. 写入/建索引落点(触发 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 全文索引)
  4. lance 的 Spill 错误发生在上述某个 LanceDB 异步操作内部(Rust 层)。

疑似根因(待负责人确认)

Spill has sent an error 是 LanceDB 在内存不足时把中间结果 spill 到磁盘的执行路径报错,常见诱因:

  • lancedb 0.34.0 的已知/回归 bug(spill executor 在某些数据规模或并发下崩);
  • FTS create_indexadd/merge_insert 在该数据量下触发 spill;
  • 也可能与之前记录过的 lance 自动 optimize/encoding bug 同源。

(本人无法在 EverOS 仓库改代码,故整理证据交由负责人定位。)

复现要点

  1. 用 raven TUI 正常对话,产生新的 episode md(落 ~/.everos/raven/.index)。
  2. cascade worker 扫到该 md → embed → 写 LanceDB → 命中上述 Spill 错误。
  3. system.dbmd_change_state,可见对应 episode status=failed

建议排查方向

  1. 单独跑一次对 failed episode 的 handler,开 lancedb / lance 的 debug/backtrace(RUST_BACKTRACE=1),拿到 lance 内部完整栈,确认是 add 还是 create_index(FTS) 触发 spill。
  2. 试 bump / 回退 lancedb 版本(0.34.0 → 相邻版本)看是否为版本回归。
  3. 评估该数据量是否真需要 spill;若是 lance bug,考虑限制批量大小 / 关闭相关优化 / 给 worker 加降级路径(写失败时至少保留可 flat-scan 的回退,避免 recall 整段丢失)。
  4. 对已 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 无关。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions