fix(lancedb): detect schema type drift and add cascade rebuild recovery - #354
fix(lancedb): detect schema type drift and add cascade rebuild recovery#354gloryfromca wants to merge 2 commits into
Conversation
verify_business_schemas only compared column names, so a column whose on-disk Arrow type had drifted (name unchanged) slipped through and detonated later inside merge_insert as an opaque LanceError(IO) "Spill has sent an error" (#337). Now compare each shared column's Arrow type against schema.to_arrow_schema() — the exact schema get_table builds tables from, so a healthy table never false-positives. Reproduced #337 byte-identically: an episode.subject_vector column left as string or null by an older build, plus a real 1024-d vector on upsert, yields the exact crash. No lancedb version (0.13-0.34) renders Optional[Vector] as a non-vector type, so the startup guard is what should catch it — not the runtime. Add `everos cascade rebuild` as the safe recovery: it drops the business LanceDB tables and re-indexes from markdown, skipping the verify guard (which the drift would otherwise trip on startup). Unlike removing only .index/lancedb it re-populates already-done entries (reset_all clears the cascade queue); unlike removing all of .index it preserves unprocessed_buffer (messages not yet extracted). Fixes #337.
07b4704 to
fe65af2
Compare
Add the `everos cascade rebuild` command to the runbook, CLI, and how-memory-works docs. Correct the old recovery guidance: a bare `rm -rf .index/lancedb` leaves md_change_state marked `done`, so the scanner skips those files and the index comes back empty — the runbook previously claimed a full repopulation that does not happen. `cascade rebuild` is the safe path (re-populates done entries, preserves unprocessed_buffer). Also document that verify now checks column types.
|
在 1.1.3 上独立复现,确认这个 PR 的诊断和恢复路径都对。补几个数据点,顺便催一下合并。 1.1.3 仍复现,且已发布版本都还没带上这个修复
没有本 PR 的排查成本(正是它要消灭的)在不知道 #337 的情况下,从症状定位到根因需要逐一排除:磁盘空间(剩余 237G)、文件描述符(116/1048576)、 最具误导性的一点:手动对同一张表做 本 PR 的启动期类型比对能把这一整段直接变成一条明确报错,价值很大。 手动恢复已验证可行(给还没等到合并的人)在 1.1.3 上按本 PR 的思路手动执行,结果正常:
结果:episode 19 行 -> 88 行(补回了积压 18 天的记录),其中 69 行带 这正是本 PR 的 两个本 PR 未覆盖的点不影响本 PR 合并,单独说明(另开 issue 跟踪):
能否优先合并?目前每个新装/老库用户遇到这个问题,拿到的仍是那条看不懂的 IO 错误。 |
CascadeOrchestrator dropped the embedder param when embedding became a soft dependency (main); fold the schema-drift integration test onto it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Folded into #379 (consolidated LanceDB hardening PR, rebased on latest main + validated by the storage soak). Commit preserved there. |
Problem — the root cause behind #337
verify_business_schemas(the startup guard) only compared column names against the current schema. A column whose on-disk Arrow type had drifted — name unchanged — sailed through and detonated much later, deep insidemerge_insert, as the notoriously opaque:This is exactly #337: an
episode.subject_vectorcolumn left asstring(ornull) by an older build, while the current schema declares a 1024-dfixed_size_list. Writing a real vector into that column is a pyarrow type error that lance wraps as the "Spill" IO error.Verified
subject_vector(stringandnull) column + a real 1024-d vector through the realLanceRepoBase.upsert()path yields the exact cascade worker fails to index episodes: LanceDBSpill has sent an error(IO) #337 error; a correctly-typed table accepts the same records.TypeError, 0.20+ render the correctfixed_size_list), and lance never silently adds a mistyped column — so the drift originates from a build that declared the field differently, and the guard is what should have caught it at startup.Changes
1. Type-aware
verify_business_schemas— compare each shared column's Arrow type againstschema.to_arrow_schema()(the exact schemaget_tablebuilds tables from, so a healthy table never false-positives). On drift the startup error now names the drifted column and both types instead of the runtime Spill.2.
everos cascade rebuild— the safe recovery from a drifted/corrupt index:rm -rf ~/.everos/.index/lancedb, re-populates already-doneentries (reset_allclears the cascade queue so every md file re-enqueues) — a barermof the lancedb dir leaves the queue marked done and the index comes back empty;rm -rf ~/.everos/.index, preservesunprocessed_buffer(messages received but not yet extracted — not rebuildable from md).Tests
test_verify_schemas.py— healthy tables pass (false-positive guard);subject_vectorasstring/nullraises withtype_drift; missing column raises (unchanged);drop_business_tablesdrops + recreates the correct vector type. The type-drift tests were confirmed to fail without the fix (old guardDID NOT RAISE).test_md_change_state.py—reset_allclears every row regardless of status; noop on empty.test_cascade_cli_integration.py—cascade rebuildruns despite a drift that trips a normal command's startup verify, recreates the table with the correct type, and re-indexes md from scratch.Full unit suite +
make lint(ruff, import-linter, datetime, openapi) green.Fixes #337.