Skip to content

[Bug] store.update / compareAndUpdate 会把已有记忆的 embedding 清空(重启后全部向量丢失,语义搜索降级 keyword) #3

Closed

Description

@heptaspirit

环境

  • dsh-mneme 0.2.10 / 0.2.11 / 0.3.0 均存在
  • Windows 11,dsh web profile

现象

每次重启 dsh,记忆库中所有记忆的 embedding 列被置空(UPDATE 置 NULL),
/api/dsh-mneme/semantic 的 embeddedCount 归零,语义搜索静默降级为 keyword。
手动 reindex(/api/dsh-mneme/vector-reindex)可恢复向量,但下次重启又全部清空。

触发路径

启动时执行 mirror 合并回库(mergeHumanEdits,读 md 镜像 → store.update)→
不带 embedding 字段的 update → 向量被清。

根因(代码级)

  1. lib/store.js 的 toRow() 刻意剥离 embedding 字段(避免向量经 API 外泄,合理设计);
  2. 但 update() 与 compareAndUpdate() 的向量保留逻辑写的是
    existing.embedding ?? null,而 existing = getById(id) → toRow →
    existing.embedding 恒为 undefined → ?? null 兜底生效 → 向量被清成 NULL;
  3. 代码意图显然是"未传 embedding 时保留旧向量"(与 patch.content ?? existing.content
    等其他字段的保留逻辑一致),因此这是 toRow 与 update 之间的耦合缺陷。

复现步骤

  1. 配置 embedProvider: local,记忆库已有向量(embeddedCount > 0);
  2. 重启 dsh(触发启动 mirror 合并 → mergeHumanEdits → store.update);
  3. 重启后查库:SELECT COUNT(*) FROM memories WHERE embedding IS NOT NULL → 0。

影响

每次重启丢失全部向量,语义搜索静默失效;需要人工 reindex 且无法持久。

修复建议(两处)

update() 和 compareAndUpdate() 中,改为直接从原始行读取 embedding 列:

// 原:
const embedding = patch.embedding !== undefined
  ? (Array.isArray(patch.embedding) && patch.embedding.length ? JSON.stringify(patch.embedding) : null)
  : existing.embedding ?? null;

// 改:
const existingEmbedding = db.prepare("SELECT embedding FROM memories WHERE id = ?").get(id)?.embedding ?? null;
const embedding = patch.embedding !== undefined
  ? (Array.isArray(patch.embedding) && patch.embedding.length ? JSON.stringify(patch.embedding) : null)
  : existingEmbedding;

Activity

  1. Anans-Amarre commented on Aug 16, 2026

    @Anans-Amarre
    Collaborator

    感谢这么详尽的 bug 报告!@heptaspirit 你定位得非常准——toRow() 剥离 embedding 与 update() 的 existing.embedding ?? null 兜底确实是耦合缺陷。

    我们已核实并确认:

    • 主 bug 已在 v0.3.x 修复:update() / compareAndUpdate() 现在只在 patch.embedding !== undefined 时才写该列,否则保留现有向量(不会清空)
    • 残留问题确认存在:mergeHumanEdits(启动 mirror 合并回库)更新记忆后没有触发 re-embed,所以人工编辑过的记忆向量与内容可能不一致

    修复方向:mergeHumanEdits 的 update 后补一次 scheduleEmbed,与 saveWithDedupe 路径对齐。已列入待办,会尽快修复。再次感谢严谨复现!

  2. added
    bug功能异常、崩溃、数据错误(agent 诊断 → 人工确认)
    on Aug 16, 2026
  3. modusensus commented on Aug 16, 2026

    @modusensus
    Member

    已在v0.3.3修复,感谢建议!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bug功能异常、崩溃、数据错误(agent 诊断 → 人工确认)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions