fix: add actionable remediation hints for memory search embedding errors#54916
fix: add actionable remediation hints for memory search embedding errors#54916QihongRuan wants to merge 2 commits into
Conversation
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
Greptile SummaryThis PR adds actionable remediation hints to Confidence Score: 4/5Safe 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.
|
| 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)
-
src/agents/tools/memory-tool.ts, line 87-90 (link)Missing hint in
catcherror pathThe
catchblock returns adisabled: trueresult with anerrormessage but nohint, while the!managerpath directly above now includesresolveMemoryErrorHint. 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
| 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")) { |
There was a problem hiding this 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:
| 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.| ): string | null { | ||
| const lower = error.toLowerCase(); | ||
|
|
||
| if (lower.includes("leaked") || lower.includes("reported as leaked")) { |
There was a problem hiding this comment.
"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.
| 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)
|
Hi maintainers, This PR is currently behind main by ~13K commits and the target files have been refactored: Old structure (this PR targets):
New structure (current main):
The bot-reported issues (P1 regex pattern, P2 redundant check) have been fixed in commit Options:
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
|
Hi maintainers, This PR is currently behind main by ~13K commits and the target files have been refactored: Old structure (this PR targets):
New structure (current main):
The bot-reported issues (P1 regex pattern, P2 redundant check) have been fixed in commit Options:
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! |
|
Hi maintainers, This PR is currently behind main by ~13K commits and the target files have been refactored: Old structure (this PR targets):
New structure (current main):
The bot-reported issues (P1 regex pattern, P2 redundant check) have been fixed in commit Options:
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! |
|
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 (
Please review #55684 instead. Thanks! |
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)
Summary
When
memory_searchfails 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
Fixline below the error with step-by-step recovery instructions:2. Tool result:
memory_search(src/agents/tools/memory-tool.ts)Adds a
hintfield 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
leaked/reported as leakedopenclaw configure+ restart gatewayquota/rate limit/429401/unauthorizedopenclaw configureMotivation
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_searchfor weeks. The fix required reading OpenClaw source code to find the stale key inauth-profiles.json— this PR ensures future users get clear, actionable guidance instead.Closes #54912