Skip to content

fix(doctor): suppress false-positive local embedding warning when gateway probe skipped [AI-assisted]#95177

Closed
ml12580 wants to merge 1 commit into
openclaw:mainfrom
ml12580:fix/vuln-92582
Closed

fix(doctor): suppress false-positive local embedding warning when gateway probe skipped [AI-assisted]#95177
ml12580 wants to merge 1 commit into
openclaw:mainfrom
ml12580:fix/vuln-92582

Conversation

@ml12580

@ml12580 ml12580 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

[AI-assisted] This PR was generated using Claude Code.

Closes #92582

What Problem This Solves

Fixes an issue where users who configured agents.defaults.memorySearch.provider to "local" (bundled Hugging Face GGUF embeddings) would see openclaw doctor — and openclaw doctor --deep — falsely report:

Memory search provider is set to "local", but local embeddings are not confirmed ready.
Fix (pick one):
- Install the llama.cpp provider plugin: openclaw plugins install @openclaw/llama-cpp-provider
- Set a local GGUF model path in config
...

…even when openclaw memory status --deep confirms the full memory stack is healthy (Embeddings: ready, Vector store: ready, etc.). The warning implies the configured local provider is broken when it is not — a false positive that sends users chasing a non-existent problem (reinstalling plugins, reconfiguring model paths).

Why This Change Was Made

openclaw doctor probes gateway memory readiness via probeGatewayMemoryStatus, which always calls doctor.memory.status with probe: false. The gateway therefore returns checked: false + skipped: true to signal "readiness was not tested" — for both doctor and doctor --deep.

In noteMemorySearchHealth, the key-optional provider branch already treats skipped: true as "not tested, do not warn" and returns early. The local provider branch, however, only suppressed its warning when checked && ready; it had no skipped guard, so a skipped probe fell straight through to the alarming "not confirmed ready" warning.

This PR mirrors the existing key-optional guard onto the local branch: when the probe was intentionally skipped, return without warning. A transport timeout still sets checked: false with skipped absent, so it continues to fall through to the warning (unchanged). This is a focused, symmetric 3-line guard plus a regression test — it does not change probe behavior, gateway calls, or any ready/not-ready path that was already firing correctly.

Non-goal: wiring --deep to actually run the embedding probe (probe: true) is a larger change to the gateway probe transport and is intentionally out of scope for this false-positive fix.

User Impact

Users running openclaw doctor or openclaw doctor --deep with a healthy local embedding provider no longer see a false "local embeddings are not confirmed ready" warning that implies their provider is broken. The doctor output stays quiet when readiness was simply not probed, consistent with how key-optional providers (ollama, lmstudio, openai-compatible) already behave. Users can still run openclaw memory status --deep for an authoritative readiness check, and genuine failures (probe ran and reported not-ready, or timed out) still produce the warning.

Evidence

Root cause confirmed in source: src/commands/doctor-memory-search.ts, the provider === "local" branch lacked the skipped guard that the key-optional branch already had.

Regression test added: src/commands/doctor-memory-search.test.ts — "does not warn when local provider probe was skipped (skipped: true)". It drives the real noteMemorySearchHealth with a local provider whose gateway probe was skipped ({ checked: false, ready: false, skipped: true }), exactly the probe: false path openclaw doctor uses.

BEFORE fix (unpatched main) — the false-positive warning is emitted:

FAIL  src/commands/doctor-memory-search.test.ts > noteMemorySearchHealth > does not warn when local provider probe was skipped (skipped: true)
AssertionError: expected "vi.fn()" to not be called at all, but actually been called 1 times

1st vi.fn() call:
  "Memory search provider is set to \"local\" and a local model path is configured, but local embeddings are not confirmed ready.
  Fix (pick one):
  - Install the llama.cpp provider plugin: openclaw plugins install @openclaw/llama-cpp-provider
  - Set a local GGUF model path in config
  - Switch to a remote provider: openclaw config set agents.defaults.memorySearch.provider github-copilot
  Verify: openclaw memory status --deep"
Number of calls: 1

AFTER fix — the same input emits no warning, and the full suite (including the existing "local provider readiness probe is inconclusive" timeout case, which still warns) passes:

Test Files  1 passed (1)
     Tests  50 passed (50)

The existing timeout case (checked: false, no skipped, error gateway memory probe timed out: ...) still produces the warning, confirming the fix only suppresses the intentional-skip case and does not silence real diagnostic signals.

Real behavior proof

  • Behavior or issue addressed: openclaw doctor false-positive "local embeddings are not confirmed ready" warning for a configured local memory provider when the gateway memory probe was skipped (readiness not checked).
  • Environment used for testing: Windows 10, Node v22.22.3, OpenClaw 2026.6.8 built from this PR branch (base upstream/main 49b0487 + fix), invoked via the real openclaw doctor CLI.
  • Steps to reproduce: configure agents.defaults.memorySearch.provider=local with a local modelPath (hf: GGUF URI) and a gateway auth token stored as an exec SecretRef, then run openclaw doctor without --allow-exec. Doctor skips the gateway memory probe (readiness not checked — the exact skipped-probe condition from issue Bug: doctor falsely warns local memory embeddings are not ready #92582), so noteMemorySearchHealth receives { checked: false, ready: false, skipped: true }.
  • Observed result before fix: doctor emitted a "Memory search" note — "Memory search provider is set to "local" and a local model path is configured, but local embeddings are not confirmed ready" plus a remediation list.
  • Observed result after fix: doctor emitted 0 "Memory search" notes for the skipped-probe case; the "Gateway health probes skipped because gateway credentials use an exec SecretRef" note still fires, confirming the same skipped-probe path was exercised.
  • Evidence after fix (terminal capture):
$ openclaw doctor --non-interactive --no-workspace-suggestions          # AFTER fix (this PR)
...
◇  Gateway ────────────────────────────────────────────────────────────────╮
│  Gateway health probes skipped because gateway credentials use an exec   │
│  SecretRef. Run `openclaw doctor --allow-exec` to verify Gateway health  │
│  with exec SecretRefs.                                                   │
├──────────────────────────────────────────────────────────────────────────╯
... (no "Memory search" section is emitted — readiness was not probed)

$ grep -ciE 'Memory search provider|local embeddings|not confirmed ready' after-doctor.txt
0

Before fix (unpatched), the same openclaw doctor run emits the false-positive warning while the gateway probe is skipped:

$ openclaw doctor --non-interactive --no-workspace-suggestions          # BEFORE fix (main)
...
◇  Gateway ────────────────────────────────────────────────────────────────╮
│  Gateway health probes skipped because gateway credentials use an exec   │
│  SecretRef. Run `openclaw doctor --allow-exec` to verify Gateway health  │
│  with exec SecretRefs.                                                   │
├──────────────────────────────────────────────────────────────────────────╯
...
◇  Memory search ──────────────────────────────────────────────────────╮
│  Memory search provider is set to "local" and a local model path is  │
│  configured, but local embeddings are not confirmed ready.           │
│  Fix (pick one):                                                     │
│  - Install the llama.cpp provider plugin: openclaw plugins install   │
│    @openclaw/llama-cpp-provider                                      │
│  - Set a local GGUF model path in config                             │
│  - Switch to a remote provider: openclaw config set                  │
│    agents.defaults.memorySearch.provider github-copilot              │
│  Verify: openclaw memory status --deep                               │
├──────────────────────────────────────────────────────────────────────╯

Compatibility / Migration

No public API, config, or CLI behavior change for healthy or genuinely-broken setups. The only behavioral change: a skipped probe no longer emits a false-positive warning for the local provider — matching the existing key-optional provider behavior. No migration required.

Failure Recovery

Revert the single commit. The change is isolated to the local-provider branch guard in noteMemorySearchHealth.

Risks and Mitigations

  • Risk: a user with provider: "local" and no model path configured who runs openclaw doctor (no --deep) no longer gets the "set a local GGUF model path" hint when the probe is skipped. Mitigation: this matches the existing key-optional provider behavior; openclaw doctor --deep / openclaw memory status --deep remain the authoritative readiness checks and the warning still fires when the probe actually runs and reports not-ready.
  • No security, message-delivery, availability, or compatibility boundary is touched.

What was not tested

  • macOS / Linux not tested (Windows-only local environment); the guarded code path is platform-agnostic.
  • Swift host-env-policy check (pnpm check:host-env-policy:swift) skipped on Windows (no Swift toolchain).
  • pnpm format:check reports 157 pre-existing format findings across the repo on a clean synced main (e.g. ui/src/...); the two files touched by this PR pass oxfmt --check cleanly.

…eway probe was skipped

The local memory provider branch in noteMemorySearchHealth only suppressed its
"local embeddings are not confirmed ready" warning when the gateway probe
reported checked && ready. When `openclaw doctor` (or `openclaw doctor --deep`)
ran, the gateway memory probe used the probe:false path and returned
checked:false + skipped:true, meaning readiness was never tested — but the
local branch still emitted the alarming "not confirmed ready" warning, a false
positive that implied a healthy local embedding stack was broken.

Mirror the existing key-optional provider branch: when the probe was
intentionally skipped, return without warning. A transport timeout still sets
checked:false with skipped absent, so it continues to fall through to the
warning. Fixes openclaw#92582.
@openclaw-barnacle openclaw-barnacle Bot added commands Command implementations size: XS labels Jun 20, 2026
@clawsweeper

clawsweeper Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close this PR as superseded: it contains the same central skipped-probe fix as a proof-sufficient, mergeable sibling, but its unconditional skipped return can also hide the existing diagnostic for an unavailable configured local model path.

Root-cause cluster
Relationship: superseded
Canonical: #95393
Summary: This PR is a duplicate guard-only candidate for the local doctor skipped-probe warning, but the canonical sibling has sufficient proof and a safer diagnostic-preserving guard.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Canonical path: Land the canonical sibling that suppresses the skipped-probe false positive while preserving unavailable local model diagnostics, then close the overlapping branches against that path.

So I’m closing this here because the remaining work is already tracked in the canonical issue.

Review details

Best possible solution:

Land the canonical sibling that suppresses the skipped-probe false positive while preserving unavailable local model diagnostics, then close the overlapping branches against that path.

Do we have a high-confidence way to reproduce the issue?

Yes at source level: the PR returns on gatewayMemoryProbe.skipped before checking hasLocalEmbeddings, so a skipped probe with an unavailable configured local model path produces no doctor warning. The linked user issue also has terminal output for the original false-positive path.

Is this the best way to solve the issue?

No. The skipped-probe guard is the right local area, but this branch is not the best fix because #95393 keeps the same false-positive suppression while preserving missing local-model diagnostics.

Security review:

Security review cleared: The diff only changes doctor diagnostic control flow and a colocated Vitest test; it adds no dependency, workflow, secret, permission, package, or supply-chain surface.

AGENTS.md: found and applied where relevant.

What I checked:

  • Current local warning path: Current main's local provider branch returns only when the gateway probe is checked and ready, then computes local model availability and emits the local embeddings warning. (src/commands/doctor-memory-search.ts:470, 3bed73f24994)
  • Skipped probe reaches memory renderer: The doctor flow can set gatewayMemoryProbe to { checked: false, ready: false, skipped: true } when gateway probes are intentionally skipped and then passes that value into noteMemorySearchHealth. (src/flows/doctor-health-contributions.ts:976, 3bed73f24994)
  • This PR over-suppresses local diagnostics: The PR adds an unconditional skipped-probe return before hasLocalEmbeddings runs, so a skipped gateway probe also suppresses the missing or unavailable local model-path diagnostic. (src/commands/doctor-memory-search.ts:483, 91fd25617acd)
  • Superseding sibling preserves the diagnostic: The sibling PR keeps the same skipped-probe suppression but adds hasUnavailableConfiguredLocalModel and a regression test so unavailable configured local model paths still warn. (src/commands/doctor-memory-search.ts:472, f6ab4a6535ea)
  • Canonical sibling is viable: The sibling PR is open, mergeable, labeled proof:sufficient and ready for maintainer look, and its status check rollup shows successful relevant checks at the current head. (f6ab4a6535ea)
  • Feature history: The local memory doctor branch has recent history around the llama.cpp provider split and prior skipped-probe handling, which identifies likely routing owners for this area. (src/commands/doctor-memory-search.ts:470, 31371101678d)

Likely related people:

  • vincentkoc: Recent current-main blame touches the doctor memory-search branch, and the superseding sibling includes a Vincent Koc commit preserving skipped local model diagnostics. (role: recent area contributor and canonical sibling contributor; confidence: high; commits: d38fb7456a2a, f6ab4a6535ea; files: src/commands/doctor-memory-search.ts, src/commands/doctor-memory-search.test.ts)
  • Onur Solmaz: Commit 3137110 moved the local llama.cpp runtime to a provider plugin and changed the local doctor memory-search branch and tests. (role: introduced current local-provider behavior; confidence: high; commits: 31371101678d; files: src/commands/doctor-memory-search.ts, src/commands/doctor-memory-search.test.ts)
  • hclsys: Prior skipped-probe commits added the skipped discriminator and sibling-provider renderer invariant that this local-provider fix should follow. (role: adjacent prior fix author; confidence: high; commits: 45082aaed3d0, 549624ffb204; files: src/commands/doctor-memory-search.ts, src/commands/doctor-gateway-health.ts, src/commands/doctor-memory-search.test.ts)

Codex review notes: model internal, reasoning high; reviewed against 3bed73f24994.

@ml12580

ml12580 commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Real openclaw doctor CLI before/after captures added to the "Real behavior proof" section — the gateway memory probe is skipped (readiness not checked) via an exec SecretRef, driving the same {checked:false,ready:false,skipped:true} path the fix guards. Before the fix doctor emits the false-positive "local embeddings are not confirmed ready" warning; after the fix it is silent (0 mentions) while the skip-path note still fires.

@clawsweeper

clawsweeper Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@ml12580

ml12580 commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 23, 2026
@ml12580

ml12580 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #95393 (merged in ce0142f), which closes #92582 with the same skipped-probe guard on the local-provider branch plus a diagnostic-preserving variant.

Per ClawSweeper's 6-20 assessment, this PR's unconditional skipped return would also mask the existing "missing local model path" diagnostic, whereas #95393 preserves it. With #92582 now closed as COMPLETED via the merged canonical sibling, this PR is redundant. Closing as superseded.

@ml12580 ml12580 closed this Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands Command implementations merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XS status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: doctor falsely warns local memory embeddings are not ready

1 participant