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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions