Skip to content

fix: add actionable remediation hints for memory search embedding errors#54916

Closed
QihongRuan wants to merge 2 commits into
openclaw:mainfrom
QihongRuan:fix/memory-search-leaked-key-guidance
Closed

fix: add actionable remediation hints for memory search embedding errors#54916
QihongRuan wants to merge 2 commits into
openclaw:mainfrom
QihongRuan:fix/memory-search-leaked-key-guidance

Conversation

@QihongRuan

Copy link
Copy Markdown

Summary

When memory_search fails due to a leaked, invalid, or quota-exhausted API key, users currently get a raw error message with no guidance on how to fix it. This PR adds actionable remediation hints in two places.

Changes

1. CLI: openclaw memory status --deep (src/cli/memory-cli.ts)

Adds a Fix line below the error with step-by-step recovery instructions:

Embeddings: unavailable
Embeddings error: gemini embeddings failed: 403 ... "reported as leaked"
Fix: Your API key was flagged as leaked by the provider. 1. Generate a new API key... 2. Update it: openclaw configure... 3. Restart the gateway: openclaw gateway restart

2. Tool result: memory_search (src/agents/tools/memory-tool.ts)

Adds a hint field to the JSON result when memory search is disabled, so agents can surface actionable guidance to users:

{
  "results": [],
  "disabled": true,
  "error": "gemini embeddings failed: 403 ...",
  "hint": "The embedding API key was flagged as leaked. Generate a new key, update it via `openclaw configure`, and restart the gateway."
}

Covered error patterns

Pattern Hint
leaked / reported as leaked Generate new key + openclaw configure + restart gateway
quota / rate limit / 429 Wait and retry, or switch provider
401 / unauthorized Key invalid/expired, update via openclaw configure

Motivation

We run OpenClaw 24/7 for quantitative research. Our Gemini API key was flagged as leaked by Google's automated scanner, which silently broke memory_search for weeks. The fix required reading OpenClaw source code to find the stale key in auth-profiles.json — this PR ensures future users get clear, actionable guidance instead.

Closes #54912

When memory_search fails due to a leaked/invalid/quota-exhausted API key,
users currently get a raw error message with no guidance on how to fix it.

This adds:
1. A 'Fix' line in 'openclaw memory status --deep' output with step-by-step
   recovery instructions (generate new key, run openclaw configure, restart).
2. A 'hint' field in the memory_search tool result so agents can surface
   actionable guidance to end users.

Covers three common failure modes:
- Leaked key (flagged by provider's automated scanner)
- Quota/rate limit exhaustion
- Invalid/expired key (401)

Closes openclaw#54912
@openclaw-barnacle openclaw-barnacle Bot added cli CLI command changes agents Agent runtime and tooling size: S labels Mar 26, 2026
@greptile-apps

greptile-apps Bot commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds actionable remediation hints to memory_search tool results and the openclaw memory status --deep CLI output when embedding errors occur (leaked key, quota exceeded, invalid auth). The motivation is solid and the implementation approach is straightforward.\n\nIssues found:\n- P1 — dead code in memory-cli.ts:63: lower.includes(\"invalid.*key\") passes a regex pattern to String.prototype.includes(), which does literal substring matching only. The condition can never match real error messages (e.g. \"invalid api key\") and should be replaced with a regex test or plain substring alternatives.\n- P2 — missing hint in memory-tool.ts catch block: The catch path returns disabled: true with an error but no hint, while the !manager path does. Errors thrown during the actual search call (which can also surface auth/quota messages) won't carry hints for agents.\n- P2 — redundant substring check: lower.includes(\"reported as leaked\") is unreachable since it's always covered by lower.includes(\"leaked\"). Appears in both changed files.

Confidence Score: 4/5

Safe to merge after fixing the includes("invalid.*key") dead-code bug; the rest of the hints work correctly.

The PR is additive and low-risk — it only appends hint/remediation fields to existing error results. The invalid.*key condition is simply dead code rather than a correctness regression (the existing 401/unauthorized checks still cover the most common auth errors). One targeted fix would make this complete.

src/cli/memory-cli.ts line 63 — the includes("invalid.*key") condition needs to be replaced with a regex test or a plain literal substring.

Important Files Changed

Filename Overview
src/cli/memory-cli.ts Adds resolveEmbeddingErrorRemediation to surface CLI fix hints for leaked/quota/auth errors. One logic bug: lower.includes("invalid.*key") uses a regex pattern as a literal string and will never match real error messages.
src/agents/tools/memory-tool.ts Adds resolveMemoryErrorHint and surfaces it in the !manager result path. The catch block is missing the same hint field, creating an inconsistency in error coverage.

Comments Outside Diff (1)

  1. src/agents/tools/memory-tool.ts, line 87-90 (link)

    P2 Missing hint in catch error path

    The catch block returns a disabled: true result with an error message but no hint, while the !manager path directly above now includes resolveMemoryErrorHint. If the embedding call itself throws (e.g., a network error surfacing a 401/quota message), agents won't get the actionable guidance.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/agents/tools/memory-tool.ts
    Line: 87-90
    
    Comment:
    **Missing hint in `catch` error path**
    
    The `catch` block returns a `disabled: true` result with an `error` message but no `hint`, while the `!manager` path directly above now includes `resolveMemoryErrorHint`. If the embedding call itself throws (e.g., a network error surfacing a 401/quota message), agents won't get the actionable guidance.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/cli/memory-cli.ts
Line: 63

Comment:
**Regex pattern used as literal substring**

`String.prototype.includes()` does not interpret regex syntax — it performs a literal substring search. The check `lower.includes("invalid.*key")` will only match if the error string literally contains the characters `invalid.*key` (including a period and asterisk), which will never happen in practice. This entire condition is effectively dead code.

To match error messages like `"invalid api key"` or `"invalid_api_key"`, use a regex test instead:

```suggestion
  if (lower.includes("401") || lower.includes("unauthorized") || /invalid.{0,10}key/.test(lower)) {
```

Or simply add `lower.includes("invalid key")` as a literal check if you prefer to avoid regex entirely.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/agents/tools/memory-tool.ts
Line: 87-90

Comment:
**Missing hint in `catch` error path**

The `catch` block returns a `disabled: true` result with an `error` message but no `hint`, while the `!manager` path directly above now includes `resolveMemoryErrorHint`. If the embedding call itself throws (e.g., a network error surfacing a 401/quota message), agents won't get the actionable guidance.

```suggestion
      } catch (err) {
        const message = err instanceof Error ? err.message : String(err);
        return jsonResult({ results: [], disabled: true, error: message, hint: resolveMemoryErrorHint(message) });
      }
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/cli/memory-cli.ts
Line: 41

Comment:
**Redundant substring check**

`"reported as leaked"` always contains `"leaked"`, so the second condition is always covered by the first and can never contribute to a match. The same pattern appears in `resolveMemoryErrorHint` in `memory-tool.ts:234`.

```suggestion
  if (lower.includes("leaked")) {
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: add actionable remediation hints fo..." | Re-trigger Greptile

Comment thread src/cli/memory-cli.ts Outdated
return "Embedding provider quota exhausted. Wait and retry, or switch provider via: openclaw configure";
}

if (lower.includes("401") || lower.includes("unauthorized") || lower.includes("invalid.*key")) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Regex pattern used as literal substring

String.prototype.includes() does not interpret regex syntax — it performs a literal substring search. The check lower.includes("invalid.*key") will only match if the error string literally contains the characters invalid.*key (including a period and asterisk), which will never happen in practice. This entire condition is effectively dead code.

To match error messages like "invalid api key" or "invalid_api_key", use a regex test instead:

Suggested change
if (lower.includes("401") || lower.includes("unauthorized") || lower.includes("invalid.*key")) {
if (lower.includes("401") || lower.includes("unauthorized") || /invalid.{0,10}key/.test(lower)) {

Or simply add lower.includes("invalid key") as a literal check if you prefer to avoid regex entirely.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cli/memory-cli.ts
Line: 63

Comment:
**Regex pattern used as literal substring**

`String.prototype.includes()` does not interpret regex syntax — it performs a literal substring search. The check `lower.includes("invalid.*key")` will only match if the error string literally contains the characters `invalid.*key` (including a period and asterisk), which will never happen in practice. This entire condition is effectively dead code.

To match error messages like `"invalid api key"` or `"invalid_api_key"`, use a regex test instead:

```suggestion
  if (lower.includes("401") || lower.includes("unauthorized") || /invalid.{0,10}key/.test(lower)) {
```

Or simply add `lower.includes("invalid key")` as a literal check if you prefer to avoid regex entirely.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread src/cli/memory-cli.ts Outdated
): string | null {
const lower = error.toLowerCase();

if (lower.includes("leaked") || lower.includes("reported as leaked")) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant substring check

"reported as leaked" always contains "leaked", so the second condition is always covered by the first and can never contribute to a match. The same pattern appears in resolveMemoryErrorHint in memory-tool.ts:234.

Suggested change
if (lower.includes("leaked") || lower.includes("reported as leaked")) {
if (lower.includes("leaked")) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cli/memory-cli.ts
Line: 41

Comment:
**Redundant substring check**

`"reported as leaked"` always contains `"leaked"`, so the second condition is always covered by the first and can never contribute to a match. The same pattern appears in `resolveMemoryErrorHint` in `memory-tool.ts:234`.

```suggestion
  if (lower.includes("leaked")) {
```

How can I resolve this? If you propose a fix, please make it concise.

- Remove redundant 'reported as leaked' check (already covered by 'leaked')
- Replace invalid regex-in-includes with literal substring checks
  (String.includes does not support regex patterns)
@QihongRuan

Copy link
Copy Markdown
Author

Hi maintainers,

This PR is currently behind main by ~13K commits and the target files have been refactored:

Old structure (this PR targets):

  • src/agents/tools/memory-tool.ts (deleted)
  • src/cli/memory-cli.ts (deleted)

New structure (current main):

  • extensions/memory-core/src/cli.ts
  • src/agents/memory-search.ts
  • Monorepo + packages architecture

The bot-reported issues (P1 regex pattern, P2 redundant check) have been fixed in commit 363b369, but the PR cannot be rebased due to the restructuring.

Options:

  1. Should I close this PR and create a new one targeting the new file structure?
  2. Or can this be manually merged/adapted by a maintainer who is familiar with the new architecture?

The feature (actionable error hints for leaked/quota-exceeded/invalid API keys) is still useful and the fixes are valid, just need to be applied to the new files.

Let me know how you would like to proceed. Thanks!

2 similar comments
@QihongRuan

Copy link
Copy Markdown
Author

Hi maintainers,

This PR is currently behind main by ~13K commits and the target files have been refactored:

Old structure (this PR targets):

  • src/agents/tools/memory-tool.ts (deleted)
  • src/cli/memory-cli.ts (deleted)

New structure (current main):

  • extensions/memory-core/src/cli.ts
  • src/agents/memory-search.ts
  • Monorepo + packages architecture

The bot-reported issues (P1 regex pattern, P2 redundant check) have been fixed in commit 363b369, but the PR cannot be rebased due to the restructuring.

Options:

  1. Should I close this PR and create a new one targeting the new file structure?
  2. Or can this be manually merged/adapted by a maintainer who is familiar with the new architecture?

The feature (actionable error hints for leaked/quota-exceeded/invalid API keys) is still useful and the fixes are valid, just need to be applied to the new files.

Let me know how you would like to proceed. Thanks!

@QihongRuan

Copy link
Copy Markdown
Author

Hi maintainers,

This PR is currently behind main by ~13K commits and the target files have been refactored:

Old structure (this PR targets):

  • src/agents/tools/memory-tool.ts (deleted)
  • src/cli/memory-cli.ts (deleted)

New structure (current main):

  • extensions/memory-core/src/cli.ts
  • src/agents/memory-search.ts
  • Monorepo + packages architecture

The bot-reported issues (P1 regex pattern, P2 redundant check) have been fixed in commit 363b369, but the PR cannot be rebased due to the restructuring.

Options:

  1. Should I close this PR and create a new one targeting the new file structure?
  2. Or can this be manually merged/adapted by a maintainer who is familiar with the new architecture?

The feature (actionable error hints for leaked/quota-exceeded/invalid API keys) is still useful and the fixes are valid, just need to be applied to the new files.

Let me know how you would like to proceed. Thanks!

@QihongRuan

Copy link
Copy Markdown
Author

Closing this PR as it cannot be rebased due to the monorepo refactoring.

Created a new PR #55684 with the same feature, targeting the current file structure (extensions/memory-core/src/). The new PR:

  • ✅ Based on latest main
  • ✅ Implements the same remediation hints
  • ✅ Addresses the bot-reported issues (no regex pattern misuse, no redundant checks)
  • ✅ Mergeable: True

Please review #55684 instead. Thanks!

@QihongRuan QihongRuan closed this Mar 27, 2026
ksylvan pushed a commit to ksylvan/openclaw that referenced this pull request Mar 27, 2026
When memory_search fails due to a leaked/invalid/quota-exhausted API key,
users/agents currently get generic error messages with no clear fix guidance.

This adds:
1. Detailed remediation hints in the memory_search tool result ('action' field)
   with step-by-step recovery instructions for:
   - Leaked keys (detected by provider scanner)
   - Quota/rate limit exhaustion
   - Invalid/expired keys (401/unauthorized)

2. A 'Fix' line in 'openclaw memory status --deep' CLI output with the same
   actionable guidance, making it easy for users to self-diagnose and recover.

Implementation:
- New helper function resolveEmbeddingErrorHint() in tools.shared.ts
  detects error patterns and returns appropriate remediation steps
- New helper function resolveEmbeddingErrorRemediation() in cli.runtime.ts
  with provider-specific env var hints (GEMINI_API_KEY, OPENAI_API_KEY, etc.)
- Both tool and CLI now surface actionable guidance instead of generic errors

Closes openclaw#54912 (original issue from PR openclaw#54916)
Supersedes PR openclaw#54916 (which targeted old file structure before monorepo refactor)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling cli CLI command changes size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

memory_search silently fails with leaked API key — no actionable recovery guidance

1 participant