Skip to content

fix: exec tool gateway crash (#68376) and memory-core dreaming bloat (#68379)#68445

Closed
mushuiyu886 wants to merge 2 commits into
openclaw:mainfrom
mushuiyu886:fix/exec-crash-memory-bloat-v3-clean
Closed

fix: exec tool gateway crash (#68376) and memory-core dreaming bloat (#68379)#68445
mushuiyu886 wants to merge 2 commits into
openclaw:mainfrom
mushuiyu886:fix/exec-crash-memory-bloat-v3-clean

Conversation

@mushuiyu886

Copy link
Copy Markdown
Contributor

Summary

Test plan

  • pnpm check passes (lint, tsgo, import cycles)
  • extensions/memory-core/src/dreaming-narrative.test.ts — all 42 tests pass
  • Scoped test for the "generates narrative and writes diary entry" case asserts split key format

…g bloat (openclaw#68379)

Addresses two production issues with improvements from code review feedback:

openclaw#68376 — exec tool gateway crash:
- Use instanceof Promise check instead of optional chaining to safely
  handle void callbacks that may return non-Promise truthy values
- Update onUpdate type to void | Promise<void>
- Add explanatory comment in catch body

openclaw#68379 — memory-core dreaming bloat:
- Use day-based session key instead of ms timestamp to reuse narrative
  sessions within the same day
- Use fs.stat for corpus size cap check before reading the full file
- Add 2MB cap on per-day session corpus files
- Build new entries object in writeStore instead of mutating caller's
  store, with 4096 entry LRU eviction cap
- Narrow scope-mismatch check to "missing scope" only (not broad
  "permission" substring)
…rrative

sessionKey uses a day-bucket for session reuse within the same calendar
day, while idempotencyKey includes the raw nowMs timestamp to stay
unique per run.  Previously both used the day-bucket, causing the
gateway to dedupe fresh narrative sweeps as stale cached results.

Also updates the test to assert the split key formats.
@openclaw-barnacle openclaw-barnacle Bot added extensions: memory-core Extension: memory-core agents Agent runtime and tooling size: S labels Apr 18, 2026
@greptile-apps

greptile-apps Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes two distinct production issues: a gateway crash from unhandled promise rejections in the exec tool's onUpdate callback (#68376), and memory/session bloat (500MB → 3.7GB) in the dreaming subsystem (#68379). The bloat fix is four-pronged: day-bucket session keys, unique-per-run idempotency keys, a 2MB corpus file cap, and a 4096-entry LRU eviction cap on the short-term recall store.

Confidence Score: 5/5

Safe to merge — all findings are P2 style concerns, and both bug fixes are targeted and correct.

The exec-tool crash fix is minimal and correctly handles the Promise rejection race. The four dreaming/memory bloat fixes are well-reasoned and match the stated goals. The only concern is the errMsg.includes("missing scope") string match for log-level branching, which is a style/robustness issue but does not affect correctness or user-facing behavior. No P0 or P1 issues found.

No files require special attention beyond the minor string-match concern in extensions/memory-core/src/dreaming-narrative.ts.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/memory-core/src/dreaming-narrative.ts
Line: 963

Comment:
**Brittle error classification via message substring match**

`errMsg.includes("missing scope")` ties the log-level branch to the current English error message wording. If the upstream error format changes (different phrasing, added prefix, localization), this silently falls through to the `warn` branch — the symptom that motivated the change would reappear without any clear signal.

Consider matching on a structured error code or type instead. If the upstream surface exposes an error code (e.g. `code === "MISSING_SCOPE"` or a typed error subclass), prefer that. As a fallback, anchoring to a more specific substring like `"missing scope: operator"` is slightly more robust, but a code-based check would be more durable.

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

Reviews (1): Last reviewed commit: "fix(memory-core): split idempotencyKey f..." | Re-trigger Greptile

// logged at info level instead of warning — they are expected when the
// plugin lacks admin scope and are not actionable by the user (#68379).
const errMsg = formatErrorMessage(cleanupErr);
if (errMsg.includes("missing scope")) {

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 Brittle error classification via message substring match

errMsg.includes("missing scope") ties the log-level branch to the current English error message wording. If the upstream error format changes (different phrasing, added prefix, localization), this silently falls through to the warn branch — the symptom that motivated the change would reappear without any clear signal.

Consider matching on a structured error code or type instead. If the upstream surface exposes an error code (e.g. code === "MISSING_SCOPE" or a typed error subclass), prefer that. As a fallback, anchoring to a more specific substring like "missing scope: operator" is slightly more robust, but a code-based check would be more durable.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/memory-core/src/dreaming-narrative.ts
Line: 963

Comment:
**Brittle error classification via message substring match**

`errMsg.includes("missing scope")` ties the log-level branch to the current English error message wording. If the upstream error format changes (different phrasing, added prefix, localization), this silently falls through to the `warn` branch — the symptom that motivated the change would reappear without any clear signal.

Consider matching on a structured error code or type instead. If the upstream surface exposes an error code (e.g. `code === "MISSING_SCOPE"` or a typed error subclass), prefer that. As a fallback, anchoring to a more specific substring like `"missing scope: operator"` is slightly more robust, but a code-based check would be more durable.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The codebase does not yet expose a structured error code for scope errors — the UI layer (ui/src/ui/controllers/scope-errors.ts:16) uses the
exact same err.message.includes("missing scope: operator.read") pattern, with a comment explicitly stating "RPC scope failures do not yet
expose a dedicated structured detail code." This is a problem that requires adding structured error codes at the gateway protocol layer to
resolve properly, and is not suitable for introducing a new error type in this PR alone.

@clawsweeper

clawsweeper Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Closing this as implemented after Codex automated review.

Current main already covers the two linked bug surfaces through shipped exec restart-state hardening and memory-core dreaming safeguards; this unmerged multi-issue branch is now obsolete.

Best possible solution:

Close this PR as obsolete because current main already covers the linked production failures. Keep the shipped restart queue and dreaming safeguards; handle any residual onUpdate/corpus/store-cap hardening as a separate focused PR against current main with tests.

What I checked:

  • PR diff and security surface: The PR diff only changes TypeScript source/tests under agents and memory-core. It does not touch CI workflows, dependency sources, lockfiles, install/build/release scripts, package publishing metadata, downloaded artifacts, generated/vendor files, or secret/permission configuration. Greptile reported no P0/P1 findings and one non-blocking P2 style concern; the contributor replied that structured scope-error codes are not currently exposed. (05af679442ad)
  • Exec restart hardening is present: Current main patches legacy command queue singleton state missing activeTaskWaiters after SIGUSR1 in-process restarts, the failure mode cited by the maintainer close comment for the linked exec crash report. (src/process/command-queue.ts:70, 7d9dc8cf24fc)
  • Gateway restart resets command lanes: The gateway run loop calls resetAllLanes() on restart iteration so interrupted tasks from the previous lifecycle do not leave active counts elevated and block new work. (src/cli/gateway-cli/run-loop.ts:421, 7d9dc8cf24fc)
  • Exec restart regression coverage exists: A regression test plants a legacy-shaped queue singleton and verifies resetAllLanes() and waitForActiveTasks() do not throw, covering the shipped restart recovery fix. (src/process/command-queue.test.ts:381, 7d9dc8cf24fc)
  • Dreaming is opt-in by default: Runtime default sets DEFAULT_MEMORY_DREAMING_ENABLED to false; docs also state Dreaming is opt-in and disabled by default, addressing the linked report's default/no-control concern. (src/memory-host-sdk/dreaming.ts:12, 7d9dc8cf24fc)
  • Dreaming session ingestion is bounded: Current main bounds session ingestion by messages per sweep, messages per file, tracked messages per session, and tracked scopes; it also trims stored seen-message state. (extensions/memory-core/src/dreaming-phases.ts:89, 7d9dc8cf24fc)

So I’m closing this as already implemented rather than keeping a duplicate issue open.

Codex Review notes: model gpt-5.5, reasoning high; reviewed against 7d9dc8cf24fc; fix evidence: release v2026.4.23, commit a9797214338b.

@clawsweeper clawsweeper Bot closed this Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling extensions: memory-core Extension: memory-core size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant