fix(memory): fall back to platform-specific sqlite-vec variant when meta package is missing#77851
Conversation
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. high confidence. Current main source imports only the meta sqlite-vec package before returning unavailable, and the PR discussion supplies before/after terminal proof with only platform packages installed on Linux x64 and macOS arm64. Real behavior proof Next step before merge Security Review detailsBest possible solution: Land this PR or an equivalent memory-host SDK fallback after maintainer review and exact-head CI, preserving explicit extensionPath precedence and the existing meta-package path. Do we have a high-confidence way to reproduce the issue? Yes, high confidence. Current main source imports only the meta sqlite-vec package before returning unavailable, and the PR discussion supplies before/after terminal proof with only platform packages installed on Linux x64 and macOS arm64. Is this the best way to solve the issue? Yes. Resolving the platform package's exported vec0 native-file subpath matches sqlite-vec 0.1.9 package metadata and confines the behavior change to the missing-meta fallback. What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against d9175464d732. |
deb271d to
939b27e
Compare
|
Confirming the diagnosis from a production gateway on macOS arm64, Node 25.5.0, OpenClaw 2026.5.2 stable. Pre-bump our The platform-specific package is what's actually doing the work; the meta Validating the fix shape: the proposed fallback to platform-specific resolution from the meta package's expected location matches exactly the install layout we have. PR description aligns with #77838 (5.4 regression) and #77781 (Node 24+ surfacing). Both should clear once this lands. We're on the 5.5 holdback list (also blocking on #78407), and once this PR plus a 5.5-1 patch land we plan to bump. Ship-vote signal: production gateway with 1458 indexed memory chunks across 102 files actively using vector recall — losing LGTM in concept; happy to test on the actual install once merged. |
|
Real-behavior proof, per Setup (broken-meta install layout matching 5.4/5.5): Two harnesses mirror Before (PR base After (PR HEAD The fallback resolves Environment:
Combined with the Linux x64 evidence in the PR description, the platform-variant fallback is verified on both currently-published darwin-arm64 and linux-x64 variants. PR also resolves #77781 (Node 24+ surfacing of the same issue) and #77838 (5.4 regression) cleanly. Suggest merging when CI is green. Re-review progress:
|
8b8c623 to
df21fb3
Compare
df21fb3 to
03cfe8a
Compare
Resolve the sqlite-vec platform package exported native extension when the meta package is absent, preserving explicit extensionPath priority and keeping the existing config hint on load failures. Adds coverage for the real exported vec0 subpath so package.json export-map regressions fail in tests. Fixes openclaw#77838. Co-authored-by: corevibe555 <[email protected]>
03cfe8a to
9781cfd
Compare
|
Landed in a1fc955. Thanks @corevibe555. Proof:
Re-review progress:
|
Summary
AI-assisted PR (Claude Code). Bug fix for #77838.
npm install -g openclaw@latestlands the platform-specificsqlite-vec-*package as an optional dep but does not always install the metasqlite-vecpackage. Memory-search startup fails withCannot find package 'sqlite-vec'even thoughvec0.{so,dylib,dll}is on disk inside the variant package.agents.defaults.memorySearch.store.vector.extensionPathat a loadable extension. This regressed whensqlite-vecmoved tooptionalDependencies.loadSqliteVecExtensionthat, whenimport('sqlite-vec')fails with a missing-package error, resolves the platform variant package directly viarequire.resolve('${pkg}/${file}')(the variant's documentedexportssubpath forvec0.{so,dylib,dll}) and loads the extension from that path. Errors from the fallback preserve theextensionPathconfig hint.sqlite-vecpackage, the memory-search schema, agent config keys, or the public SDK. No behavior change when the metasqlite-vecpackage is present (the original code path still wins) or whenextensionPathis set explicitly.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Real behavior proof
Behavior or issue addressed:
Issue sqlite-vec import fails after upgrade to 2026.5.4 (regression from 5.3) #77838. After
npm install -g openclaw@latestthe metasqlite-vecpackage is missing while the platform variant package (e.g.sqlite-vec-linux-x64) is installed. Memory-search startup fails withCannot find package 'sqlite-vec'even thoughvec0.sois on disk. This PR makesloadSqliteVecExtensionfall back to loading the loadable extension straight from the platform variant package.Real environment tested:
Linux 6.8.0-106-generic, x86_64, Node v22.22.2,
node:sqlite(experimental). Branchfix/sqlite-vec-platform-variant-fallbackat HEADdf21fb3ecb. Repro directory/tmp/sqlite-vec-proofwith a freshnpm init -yandnpm install [email protected]only — metasqlite-vecdeliberately not installed, mirroring the broken global-install state.Exact steps or command run after this patch:
repro.mjsandrepro-before.mjsinline the resolver frompackages/memory-host-sdk/src/host/sqlite-vec-platform-variant.ts(patched vs original) and callDatabaseSync(...).loadExtension(...)against the real installedvec0.so.Evidence after fix (terminal capture, copied live output):
Observed result after fix:
Live execution shows
vec_version() = 'v0.1.9'andvec_distance_L2([1,2,3],[4,6,8]) = 7.071067810058594—vec0.sowas loaded byDatabaseSync.loadExtensionvia the patched resolver, with no metasqlite-vecpackage installed. The before-run confirms the originally proposed resolver hitERR_PACKAGE_PATH_NOT_EXPORTEDbecausesqlite-vec-linux-x64'spackage.jsonexposes only./vec0.soinexports. Switching the resolver torequire.resolve('${pkg}/${file}')(the variant's documented export subpath) makes the fallback work end-to-end. Existing unit tests still pass after the change (Tests 4 passed (4)), andpnpm check:changedis green.What was not tested:
macOS (
darwin-x64,darwin-arm64) and Windows (win32-x64) variant packages were not installed on this Linux box, so theirloadExtensionpaths were not live-loaded; they share the sameexportsshape aslinux-x64(a single./vec0.{dylib,dll}subpath), so the same resolver path is expected to apply but is unverified on those platforms.linux-arm64was not exercised on arm64 hardware. The full openclaw memory-search startup wiring throughloadSqliteVecExtensionwas not driven via the CLI — only the inlined resolver +node:sqliteloadExtensioncall that the function delegates to.Before evidence (optional but encouraged):
The "BEFORE FIX" block above (
node repro-before.mjs) is the before-state evidence — original resolver against the same real install layout, returningundefinedand triggering the user-facing "sqlite-vec package is not installed" error path.Root Cause (if applicable)
optionalDependenciesmove on the metasqlite-vecpackage means npm's global-install layout can drop the meta package while keeping the platform variant.loadSqliteVecExtensionhad no fallback for that layout, so memory search broke on freshnpm i -g openclaw@latest.3b00b2cedb) calledrequire.resolve('${pkg}/package.json')against the variant package, but the published variant declares"exports": { "./vec0.so": ... }only —./package.jsonis not in the exports map, so under Node 22's strictexportsenforcement the resolve throwsERR_PACKAGE_PATH_NOT_EXPORTED. Thetry/catchswallowed it and the fallback never fired in real installs. The unit tests passed because theyvi.doMock'd the resolver itself.ERR_PACKAGE_PATH_NOT_EXPORTEDfrom the real published variant package was never exercised.sqlite-vecmoving tooptionalDependencies(and the variant packages declaring tightexportsmaps) coincided. Either change in isolation would not have surfaced this combination.Regression Test Plan (if applicable)
packages/memory-host-sdk/test/(or the existing co-locatedsqlite-vec.test.ts) that runsresolveSqliteVecPlatformVariant()against a real installed variant package (installed into a tmp dir during the test or via a shared fixture), with no metasqlite-vecpresent.sqlite-vec-${platform}-${arch}installed (no metasqlite-vec),resolveSqliteVecPlatformVariant()returns a non-undefinedextensionPathand that path exists on disk and is the file declared in the variant'sexportsmap.require.resolveagainst a real publishedpackage.json/exportsmap, which is the exact surface thatpackage.json-vs-vec0.sosubpath choices depend on. Mocking the resolver hides this entirely.sqlite-vec.test.tscases allvi.doMock./sqlite-vec-platform-variant.js.User-visible / Behavior Changes
sqlite-vec-${platform}-${arch}variant is present (e.g. somenpm i -g openclaw@latestupgrades), instead of erroring with "sqlite-vec package is not installed". No new config keys, no changes to error messages on the "no variant available" path, and the explicitextensionPathconfig keeps highest priority.Diagram (if applicable)
Security Impact (required)
NoNoNoNo—db.loadExtensionis already used by the existing code path; this PR only changes which path that resolved-from-installed-package extension comes from.NoYes, explain risk + mitigation: N/A. Worth noting: the resolved path comes fromrequire.resolveagainst an npm-installed package the user already chose to install; no new filesystem search or arbitrary-path loading is introduced.Repro + Verification
Environment
packages/memory-host-sdkhost codeagents.defaults.memorySearch.store.vector.extensionPath(and no per-agent override) is set, and the metasqlite-vecpackage is absent.Steps
mkdir -p /tmp/sqlite-vec-proof && cd /tmp/sqlite-vec-proof && npm init -y && npm install sqlite-vec-linux-x64— install only the variant, not the meta package, to mirror the broken global-install state.node repro-before.mjs) and confirm it returnsundefinedwithERR_PACKAGE_PATH_NOT_EXPORTED.node repro.mjs) and confirm it resolves the variant, loadsvec0.sointonode:sqliteviaDatabaseSync.loadExtension, and successfully evaluatesvec_version()andvec_distance_L2(...).Expected
undefinedagainst the real install (and the surrounding code path returns{ ok: false, error: "sqlite-vec package is not installed. ..." }).{ pkg: 'sqlite-vec-linux-x64', extensionPath: '.../vec0.so' }andloadExtensionsucceeds withvec_version() = 'v0.1.9'.Actual
Evidence
Attach at least one:
ERR_PACKAGE_PATH_NOT_EXPORTED,ERR_MODULE_NOT_FOUND,vec_version,vec_distance_L2)Human Verification (required)
sqlite-vec-linux-x64present, no metasqlite-vec) — patched resolver resolves the variant and loadsvec0.sointonode:sqlite, original resolver returnsundefinedwithERR_PACKAGE_PATH_NOT_EXPORTED.loadSqliteVecExtension(4 cases) — still passes.pnpm check:changed— green.sqlite-vecdeliberately absent from the test directory (ls node_modules/sqlite-vecreturns ENOENT) before running the repro.exportsmap confirmed via directrequire.resolveprobe (./vec0.soexported,./package.jsonnot exported).darwin-x64,darwin-arm64) and Windows (win32-x64) variants — not installed on this Linux box.linux-arm64on real arm64 hardware.loadSqliteVecExtensionfrom agent config — only the host-SDK code path was exercised.Review Conversations
Compatibility / Migration
Yes— when metasqlite-vecis present orextensionPathis set explicitly, behavior is unchanged.NoNoRisks and Mitigations
asg017/sqlite-vec) drops./vec0.{so,dylib,dll}from itsexportsmap in a future release.ERR_PACKAGE_PATH_NOT_EXPORTEDfrom the new code path; thetry/catchinresolveSqliteVecPlatformVariantreturnsundefined, andloadSqliteVecExtensionfalls back to the existing "package not installed, setextensionPath" hint so the user is not worse off than today.package.jsonwhoseexportsmap differs fromlinux-x64.vec0.{so,dylib,dll}) viaexports, which is what the resolver targets. If a divergence appears, the sametry/catchreturnsundefinedand the user sees the existing hint. A follow-up live-install integration smoke (see Regression Test Plan) would catch this earlier.AI-assisted (Claude Code). I personally ran the live repro above and confirmed behavior on this machine; AI-generated tests, mocks, and CI output are treated as supplemental.