openclaw - 💡(How to fix) Fix claude-cli Telegram DM context loss from missing-transcript race before transcript flush [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#77974Fetched 2026-05-06 06:18:33
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
2
Timeline (top)
commented ×1cross-referenced ×1mentioned ×1subscribed ×1

Root Cause

Telegram/DM sessions backed by claude-cli can intermittently lose conversation context because OpenClaw invalidates an otherwise valid Claude CLI session as missing-transcript before Claude Code has finished flushing the previous turn transcript to disk.

Fix Action

Fix / Workaround

Local Mitigation Tested

A local mitigation stopped the immediate issue:

  1. Reconstructed the missing OpenClaw direct-session transcript from the matching Claude CLI JSONL transcript.
  2. Patched the installed dist helper so claudeCliSessionTranscriptHasContent() retries briefly before returning false:
    • 9 attempts
    • 250ms delay between attempts
  3. Restarted openclaw-gateway.service.
  4. Verified the active direct session transcript exists and cleanup no longer prunes it as missing.

Code Example

[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=640 trigger=user useResume=true session=present resumeSession=<fp> reuse=reusable historyPrompt=none
[telegram] sendMessage ok chat=<redacted> message=15992

[agent/cli-backend] cli session reset: provider=claude-cli reason=missing-transcript
[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=420 trigger=user useResume=false session=none resumeSession=none reuse=invalidated:missing-transcript historyPrompt=none
[telegram] sendMessage ok chat=<redacted> message=15993

[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=398 trigger=user useResume=true session=present resumeSession=<fp> reuse=reusable historyPrompt=none
[telegram] sendMessage ok chat=<redacted> message=15994

---

[agent/cli-backend] cli session reset: provider=claude-cli reason=missing-transcript
[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=417 trigger=user useResume=false session=none resumeSession=none reuse=invalidated:missing-transcript historyPrompt=none

---

[agent/cli-backend] cli session reset: provider=claude-cli reason=missing-transcript
[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=440 trigger=user useResume=false session=none resumeSession=none reuse=invalidated:missing-transcript historyPrompt=none

---

[diagnostic] stuck session: sessionId=unknown sessionKey=agent:main:direct:<peer> state=processing age=123s queueDepth=1 reason=queued_work_without_active_run classification=stale_session_state recovery=checking
[diagnostic] stuck session recovery skipped: reason=active_reply_work action=keep_lane sessionId=<uuid> sessionKey=agent:main:direct:<peer> age=123s queueDepth=1 activeSessionId=<uuid>

---

{
  "sessionKey": "agent:main:direct:<peer>",
  "modelProvider": "claude-cli",
  "cliSessionIds": { "claude-cli": "<uuid>" },
  "cliSessionBindings": {
    "claude-cli": { "sessionId": "<uuid>", "authEpochVersion": 4 }
  }
}

---

Would prune missing transcripts: 24
prune-missing agent:main:direct:<peer>  8m ago  claude-opus-4-7 system id:<uuid>

---

<cli session A> records=98 assistant=48
<cli session B> records=46 assistant=19
<cli session C> records=74 assistant=35
<cli session D> records=76 assistant=37
<cli session E> records=76 assistant=36

---

cli session reset: provider=claude-cli reason=missing-transcript
cli exec ... useResume=false session=none resumeSession=none reuse=invalidated:missing-transcript historyPrompt=none
RAW_BUFFERClick to expand / collapse

Bug Description

Telegram/DM sessions backed by claude-cli can intermittently lose conversation context because OpenClaw invalidates an otherwise valid Claude CLI session as missing-transcript before Claude Code has finished flushing the previous turn transcript to disk.

In practice this looks like "every other Telegram message forgets context": one turn resumes correctly, then a queued/rapid follow-up turn starts fresh with no resume and no OpenClaw history reseed.

Impact

High / user-visible data-loss behavior:

  • Active Telegram DM loses conversational continuity mid-session.
  • Gateway logs show a fresh Claude session being started (useResume=false, session=none) even though the prior Claude CLI transcript exists shortly afterward and contains assistant messages.
  • If the OpenClaw session transcript file is also missing/stale, fallback reseeding is unavailable (historyPrompt=none), compounding the amnesia.

Environment

  • OpenClaw: 2026.5.4 (325df3e)
  • Service: openclaw-gateway.service
  • Channel: Telegram DM
  • Agent runtime/provider: claude-cli
  • Model: claude-opus-4-7
  • Platform: Linux/systemd user service
  • Claude CLI invocation includes stream-json/replay-user-messages/live-session path

Evidence / Logs

Representative sanitized log sequence:

[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=640 trigger=user useResume=true session=present resumeSession=<fp> reuse=reusable historyPrompt=none
[telegram] sendMessage ok chat=<redacted> message=15992

[agent/cli-backend] cli session reset: provider=claude-cli reason=missing-transcript
[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=420 trigger=user useResume=false session=none resumeSession=none reuse=invalidated:missing-transcript historyPrompt=none
[telegram] sendMessage ok chat=<redacted> message=15993

[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=398 trigger=user useResume=true session=present resumeSession=<fp> reuse=reusable historyPrompt=none
[telegram] sendMessage ok chat=<redacted> message=15994

Observed multiple times in one session, e.g. later:

[agent/cli-backend] cli session reset: provider=claude-cli reason=missing-transcript
[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=417 trigger=user useResume=false session=none resumeSession=none reuse=invalidated:missing-transcript historyPrompt=none

and:

[agent/cli-backend] cli session reset: provider=claude-cli reason=missing-transcript
[agent/cli-backend] cli exec: provider=claude-cli model=opus promptChars=440 trigger=user useResume=false session=none resumeSession=none reuse=invalidated:missing-transcript historyPrompt=none

The gateway also reported queued/stuck session state during the same window:

[diagnostic] stuck session: sessionId=unknown sessionKey=agent:main:direct:<peer> state=processing age=123s queueDepth=1 reason=queued_work_without_active_run classification=stale_session_state recovery=checking
[diagnostic] stuck session recovery skipped: reason=active_reply_work action=keep_lane sessionId=<uuid> sessionKey=agent:main:direct:<peer> age=123s queueDepth=1 activeSessionId=<uuid>

Verification

The session store had a direct DM entry with a Claude CLI binding:

{
  "sessionKey": "agent:main:direct:<peer>",
  "modelProvider": "claude-cli",
  "cliSessionIds": { "claude-cli": "<uuid>" },
  "cliSessionBindings": {
    "claude-cli": { "sessionId": "<uuid>", "authEpochVersion": 4 }
  }
}

At the time of investigation, the OpenClaw transcript path referenced by that store entry did not exist, so openclaw sessions cleanup --dry-run --fix-missing planned to prune the active DM session:

Would prune missing transcripts: 24
prune-missing agent:main:direct:<peer>  8m ago  claude-opus-4-7 system id:<uuid>

However, the corresponding Claude CLI transcript under ~/.claude/projects/.../<cliSessionId>.jsonl did exist and contained assistant messages. Examples from the same period:

<cli session A> records=98 assistant=48
<cli session B> records=46 assistant=19
<cli session C> records=74 assistant=35
<cli session D> records=76 assistant=37
<cli session E> records=76 assistant=36

This indicates OpenClaw is sometimes declaring missing-transcript too early, rather than the Claude session being genuinely absent.

Likely Root Cause

claudeCliSessionTranscriptHasContent() appears to perform a one-shot check for a Claude Code JSONL transcript containing an assistant message:

  • It scans ~/.claude/projects/*/<sessionId>.jsonl.
  • If no assistant message is visible at that exact moment, it returns false.
  • The caller invalidates the reusable CLI session with reason=missing-transcript.

For queued/rapid Telegram turns, this can race Claude Code's transcript flush. The next turn begins before the previous turn's JSONL transcript is visible/populated, so OpenClaw unnecessarily starts a fresh Claude session.

Expected Behavior

Before invalidating a claude-cli session as missing-transcript, OpenClaw should tolerate transcript flush latency, for example by:

  1. retrying the transcript-content check briefly with backoff/jitter;
  2. distinguishing "transcript not flushed yet" from "session genuinely unavailable";
  3. using OpenClaw transcript history/reseed when invalidating resume;
  4. never producing useResume=false session=none historyPrompt=none for a continuing DM when the session store has usable history/bindings.

Actual Behavior

A continuing Telegram DM sometimes gets:

cli session reset: provider=claude-cli reason=missing-transcript
cli exec ... useResume=false session=none resumeSession=none reuse=invalidated:missing-transcript historyPrompt=none

The assistant then behaves as if context was lost.

Local Mitigation Tested

A local mitigation stopped the immediate issue:

  1. Reconstructed the missing OpenClaw direct-session transcript from the matching Claude CLI JSONL transcript.
  2. Patched the installed dist helper so claudeCliSessionTranscriptHasContent() retries briefly before returning false:
    • 9 attempts
    • 250ms delay between attempts
  3. Restarted openclaw-gateway.service.
  4. Verified the active direct session transcript exists and cleanup no longer prunes it as missing.

This is only a local dist patch and will be overwritten by npm upgrades, but it strongly suggests a small upstream retry/debounce around the transcript check is the right fix.

Related Issues

Possibly related but not identical/regression-specific:

  • #70177 — Telegram DM amnesia with missing backing transcript
  • #69973 — claude-cli fallback turn loses prior context despite Claude transcript history
  • #76986 — resume chain broken / transcriptPath null

This report is specifically about the missing-transcript invalidation race in 2026.5.4 with queued/rapid Telegram DM turns.

extent analysis

TL;DR

Implement a retry mechanism with backoff in claudeCliSessionTranscriptHasContent() to tolerate transcript flush latency and prevent premature missing-transcript invalidation.

Guidance

  • Identify the claudeCliSessionTranscriptHasContent() function and modify it to include a retry mechanism with a suitable number of attempts and delay between attempts.
  • Consider distinguishing between "transcript not flushed yet" and "session genuinely unavailable" to handle cases where the transcript is still being written.
  • Review the OpenClaw transcript history/reseed logic to ensure it is used correctly when invalidating resume.
  • Verify that the useResume=false session=none historyPrompt=none scenario is handled correctly for continuing DMs with usable history/bindings.

Example

A possible implementation of the retry mechanism could be:

function claudeCliSessionTranscriptHasContent(sessionId) {
  const maxAttempts = 9;
  const delay = 250; // ms
  for (let i = 0; i < maxAttempts; i++) {
    if (/* check if transcript has content */) {
      return true;
    }
    await new Promise(resolve => setTimeout(resolve, delay));
  }
  return false;
}

Notes

The local mitigation tested in the issue report suggests that a retry mechanism can effectively resolve the issue, but a more robust solution may be needed to handle various edge cases.

Recommendation

Apply a workaround by patching the claudeCliSessionTranscriptHasContent() function to include a retry mechanism, as this has been shown to resolve the issue in the local mitigation test.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix claude-cli Telegram DM context loss from missing-transcript race before transcript flush [1 comments, 2 participants]