Files
openclaw/extensions/memory-core
BonRaynn 16ffc2507a fix(memory): prevent silent vector index degradation when embedding provider temporarily unavailable (#85704)
* fix(memory): prevent silent vector index degradation when embedding provider temporarily unavailable

Two related bugs cause complete loss of semantic vector data:

1. Promise cache deadlock in ensureProviderInitialized():
   When the embedding provider (e.g. local MLX server on port 8123) is
   temporarily unreachable at Gateway startup, loadProviderResult() throws
   and providerInitPromise becomes a permanently-cached Rejected Promise.
   The  block only clears it on success (providerInitialized=true),
   so the stale rejection blocks all future init attempts until Gateway restart.

2. Silent fts-only overwrite in runSync():
   With the provider stuck at null, shouldRunFullMemoryReindex() compares
   the stored meta.model (e.g. 'jina-embeddings-v5-text-small') against the
   runtime provider model, and since provider is null, falls through to the
   'meta.model !== fts-only' check — returning true. This triggers a full
   reindex where every file is written as fts-only, silently erasing all
   existing 11k+ semantic vectors.

Fix 1: Clear providerInitPromise in the catch block so the next call can
retry initialization (self-healing when the provider comes back online).

Fix 2: Guard runSync() — if requestedProvider is set and not 'none', but
the runtime provider is null, throw an error instead of silently degrading
to fts-only. This protects existing vector data by failing loudly.

Tested on production: 11,715 chunks + 1024-dim vectors fully preserved
after Gateway restart with the fix applied. The guard correctly blocks
sync when MLX is offline and allows normal operation when it recovers.

* fix: use this.settings.provider instead of private requestedProvider

The guard clause in runSync() was referencing this.requestedProvider
which is a private property on the MemoryIndexManager subclass and not
accessible from MemoryManagerSyncOps. Use this.settings.provider
instead, which is the same value and is accessible via the protected
abstract settings property.

* fix(memory): narrow degradation guard to only protect existing semantic indexes

The previous guard was too broad — it blocked sync for ALL non-none
provider configurations when provider was null, including the default
'auto' path where users without embedding credentials legitimately
build FTS-only indexes.

Narrow the guard to only abort when:
1. provider is null (embedding unavailable)
2. existing index metadata has a semantic model (not 'fts-only')
3. settings.provider is configured and not 'none'

This preserves the legitimate FTS-only fallback for auto/no-provider
users while still protecting existing semantic vector indexes from
silent degradation.

Reported-by: ClawSweeper (PR #85704 review)

* test: cover memory semantic index outage guard

* fix: protect semantic memory index fallback paths

* test: update memory sync harnesses

---------

Co-authored-by: Bo Yan <yaaboo-gif@users.noreply.github.com>
Co-authored-by: Yan Bo <yanbo@Mac.lan>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-25 16:15:59 +01:00
..
2026-05-10 12:37:10 +01:00
2026-05-24 02:40:16 +01:00