openclaw - ✅(Solved) Fix Bug: orphaned user repair leaves persisted transcript out of sync [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#76968Fetched 2026-05-04 04:59:55
View on GitHub
Comments
1
Participants
2
Timeline
3
Reactions
2
Author
Timeline (top)
cross-referenced ×2commented ×1

When a new prompt arrives while the previous turn left a trailing user leaf, OpenClaw merges that orphaned user content into the next prompt and moves the in-memory SessionManager leaf back to the parent. The file-backed transcript is not rewritten at that point.

That can leave the .jsonl transcript on disk with stale/orphaned user entries that no longer match the active in-memory branch. Later transcript rewrites or branch projections may then produce a current transcript with missing assistant turns or long runs of consecutive user messages, even though earlier backup files still contain those assistant turns.

Error Message

In a file-backed agent session:

Root Cause

In src/agents/pi-embedded-runner/run/attempt.ts, the orphaned trailing user repair currently changes only the in-memory leaf:

sessionManager.branch(leafEntry.parentId)
// or sessionManager.resetLeaf()

That does not remove the stale leaf from the persisted transcript file. The next run can start from disk state that still contains the orphan, so disk state, active branch state, and later rewrite/projection behavior diverge.

Fix Action

Fixed

PR fix notes

PR #76969: fix: persist orphaned user leaf repair

Description (problem / solution / changelog)

Summary

  • persist orphaned trailing user leaf removal instead of only moving the in-memory SessionManager branch
  • keep branch/reset fallback for managers that do not expose file rewrite internals
  • add unit coverage for persisted leaf removal and fallback behavior
  • fix an existing oxlint unbound-method failure in the Discord draft preview callback path that CI surfaced on this branch

Fixes #76968.

Test plan

  • pnpm lint --threads=8
  • pnpm exec vitest run src/agents/pi-embedded-runner/run/attempt.test.ts --config test/vitest/vitest.unit.config.ts
  • pnpm tsgo:test:src

Changed files

  • extensions/discord/src/monitor/message-handler.process.ts (modified, +2/-2)
  • src/agents/pi-embedded-runner/run/attempt.test.ts (modified, +49/-0)
  • src/agents/pi-embedded-runner/run/attempt.ts (modified, +39/-5)

Code Example

Merged and removed orphaned user message to prevent consecutive user turns.

---

sessionManager.branch(leafEntry.parentId)
// or sessionManager.resetLeaf()
RAW_BUFFERClick to expand / collapse

Summary

When a new prompt arrives while the previous turn left a trailing user leaf, OpenClaw merges that orphaned user content into the next prompt and moves the in-memory SessionManager leaf back to the parent. The file-backed transcript is not rewritten at that point.

That can leave the .jsonl transcript on disk with stale/orphaned user entries that no longer match the active in-memory branch. Later transcript rewrites or branch projections may then produce a current transcript with missing assistant turns or long runs of consecutive user messages, even though earlier backup files still contain those assistant turns.

Observed behavior

In a file-backed agent session:

  • the session registry entry and session .jsonl existed
  • the current transcript contained multiple consecutive user message entries
  • assistant replies that had previously been persisted were no longer present in the active .jsonl
  • backup .jsonl.bak-* files still contained some of the missing assistant entries
  • logs included the orphaned-user repair path:
Merged and removed orphaned user message to prevent consecutive user turns.

Root cause

In src/agents/pi-embedded-runner/run/attempt.ts, the orphaned trailing user repair currently changes only the in-memory leaf:

sessionManager.branch(leafEntry.parentId)
// or sessionManager.resetLeaf()

That does not remove the stale leaf from the persisted transcript file. The next run can start from disk state that still contains the orphan, so disk state, active branch state, and later rewrite/projection behavior diverge.

Expected behavior

When the orphaned user leaf is intentionally removed, the persisted SessionManager state should be updated immediately as well, so the active branch and .jsonl file stay consistent.

Fix direction

Remove the leaf entry from the underlying file-backed SessionManager entries and call its rewrite hook when available. Keep the previous in-memory branch/reset fallback for nonstandard managers.

extent analysis

TL;DR

Update the SessionManager to remove the orphaned user leaf from the persisted transcript file and call its rewrite hook when available.

Guidance

  • Identify the SessionManager implementation that handles file-backed sessions and update it to remove the orphaned user leaf from the persisted transcript file.
  • Call the rewrite hook on the SessionManager when available to ensure consistency between the in-memory branch and the persisted transcript file.
  • Verify that the updated SessionManager correctly removes the orphaned user leaf and rewrites the transcript file by checking the .jsonl file and the in-memory branch after the update.
  • Test the updated implementation with different scenarios, including consecutive user messages and assistant replies, to ensure that the transcript remains consistent.

Example

// Update the SessionManager to remove the orphaned user leaf from the persisted transcript file
sessionManager.removeLeaf(leafEntry.id);
sessionManager.rewriteHook?.();

Notes

The fix direction provided in the issue suggests removing the leaf entry from the underlying file-backed SessionManager entries and calling its rewrite hook when available. However, the exact implementation details may vary depending on the specific SessionManager implementation and the requirements of the application.

Recommendation

Apply the workaround by updating the SessionManager implementation to remove the orphaned user leaf from the persisted transcript file and call its rewrite hook when available, as this will ensure consistency between the in-memory branch and the persisted transcript file.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

When the orphaned user leaf is intentionally removed, the persisted SessionManager state should be updated immediately as well, so the active branch and .jsonl file stay consistent.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING