openclaw - ✅(Solved) Fix Bug: session reset archives are not discoverable via sessions_history, breaking context recovery after reset [1 pull requests, 1 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#56131Fetched 2026-04-08 01:44:33
View on GitHub
Comments
0
Participants
1
Timeline
7
Reactions
0
Author
Participants
Timeline (top)
referenced ×5cross-referenced ×2

When an active session is reset/rotated, the prior transcript may still exist on disk as a *.jsonl.reset.* archive, but the session tools (sessions_history, sessions_list) do not surface that prior context chain. If later system exec-completion messages arrive in a fresh session and the user says "continue", the assistant can fail to recover the original context even though the transcript still exists locally.

This caused a real failure today: I initially told the user I couldn't determine what to continue, but the prior context was still recoverable from the reset archive.

Error Message

  • line 229: openclaw:prompt-error ... error: "aborted"
  1. Trigger a prompt error / fetch failure / reset condition so the session rotates into *.jsonl.reset.*

Root Cause

  • Breaks continuity after prompt errors / fetch failures / session resets
  • Causes false "context lost" responses even when the transcript still exists
  • Makes system exec completion notifications (Exec completed, Exec failed) hard to interpret because they land in a fresh session with no visible parent context
  • Forces brittle manual forensic recovery through raw files instead of first-class tools

PR fix notes

PR #60409: fix(session): fall back to reset archive in chat.history when primary transcript is missing

Description (problem / solution / changelog)

Summary

When a session resets (daily 4 AM reset or manual /new//reset), the primary transcript is archived as <sessionId>.jsonl.reset.<timestamp>. After the reset, chat.history and sessions_history returned an empty response for that session key because readSessionMessages only checked the primary file path.

This PR makes readSessionMessages fall back to the most recent .reset.* archive when no primary transcript exists, so context is not silently lost after a reset.

Changes

  • src/gateway/session-transcript-files.fs.ts: add findLatestResetArchive(sessionId, sessionsDir) — scans for and returns the path of the most recent reset archive for a session
  • src/gateway/session-utils.fs.ts: call findLatestResetArchive as a fallback in readSessionMessages when no primary transcript is found
  • src/gateway/session-utils.fs.test.ts: 4 new tests covering the fallback (archive used when primary missing, primary preferred when both exist, latest archive picked when multiple exist, empty when neither exists)

Behaviour

  • No change when the primary transcript exists (existing path unaffected)
  • When the primary transcript is missing, the most recent .reset.<timestamp> archive is served instead of an empty result
  • Sessions with no primary and no archive still return []

Related issues

Fixes part of #45003. Also related to #42336, #56131, #57139.

Note: this PR addresses the symptom (empty chat.history after reset). Two follow-up proposals are outlined in #45003 — fixing the daily-reset trigger logic (PR 2) and exposing archives in the UI sidebar (PR 3).

Test plan

  • pnpm test -- src/gateway/session-utils.fs.test.ts — all 55 tests pass
  • No regressions in existing readSessionMessages tests
  • New tests cover all four cases: archive fallback, primary preference, latest-archive selection, empty result

Note: pnpm tsgo has a pre-existing regression in src/channels/plugins/contracts/registry.ts (missing OpenClawConfig import, introduced in upstream commit 4b93000d11) unrelated to this PR.

🤖 Generated with Claude Code

Changed files

  • src/gateway/session-transcript-files.fs.ts (modified, +54/-1)
  • src/gateway/session-utils.fs.test.ts (modified, +189/-0)
  • src/gateway/session-utils.fs.ts (modified, +18/-1)
RAW_BUFFERClick to expand / collapse

Summary

When an active session is reset/rotated, the prior transcript may still exist on disk as a *.jsonl.reset.* archive, but the session tools (sessions_history, sessions_list) do not surface that prior context chain. If later system exec-completion messages arrive in a fresh session and the user says "continue", the assistant can fail to recover the original context even though the transcript still exists locally.

This caused a real failure today: I initially told the user I couldn't determine what to continue, but the prior context was still recoverable from the reset archive.

Impact

  • Breaks continuity after prompt errors / fetch failures / session resets
  • Causes false "context lost" responses even when the transcript still exists
  • Makes system exec completion notifications (Exec completed, Exec failed) hard to interpret because they land in a fresh session with no visible parent context
  • Forces brittle manual forensic recovery through raw files instead of first-class tools

Evidence from this incident

1) Fresh oversight session looked contextless through sessions_history

Current session file:

  • /Users/octavi/.openclaw-cleanroom/agents/main/sessions/90d86798-55ff-45fd-8495-da96419583e7.jsonl

Tool output captured in that session shows:

  • sessions_history(sessionKey="agent:main:oversight", limit=20) returned only the fresh messages
  • response had truncated: true, contentTruncated: true, bytes: 2614
  • it did not indicate there was a prior reset archive containing the actual working context

Relevant line in the current transcript:

  • .../90d86798-55ff-45fd-8495-da96419583e7.jsonl line 11

2) The real context still existed in a reset transcript archive

Reset archive:

  • /Users/octavi/.openclaw-cleanroom/agents/main/sessions/572d0ce2-1eb5-4413-911c-77bad482a3ef.jsonl.reset.2026-03-28T02-40-51.286Z

That reset archive contains the prior oversight session, including:

  • successful Mentat local deployment work
  • discovery run completion
  • later continue turns
  • subsequent validation progress
  • prompt errors and fetch failures preceding the reset

Examples:

  • line 229: openclaw:prompt-error ... error: "aborted"
  • line 230: later system exec completion messages are still attached to that prior flow
  • lines 234-238: repeated fetch failed assistant errors
  • line 237: user says continue
  • line 243 onward: assistant resumes the prior discovery/leader validation work

3) What I initially missed

Because the tool-visible session history only showed the fresh session, I initially concluded the context was gone. In reality, the context was preserved in the reset archive and only became recoverable after raw file inspection.

Probable root cause

OpenClaw appears to preserve rotated session transcripts on disk, but the session retrieval layer does not expose the reset/archive chain as part of the logical session.

More specifically, there seems to be a mismatch between:

  1. physical session storage

    • prior transcript still exists as *.jsonl.reset.*
  2. logical session retrieval

    • sessions_history(sessionKey=...) only returns the latest active fragment
    • no hint that earlier archived fragments exist
  3. system event routing

    • exec completion notifications may arrive in the fresh fragment without enough provenance to reconstruct the originating work context

Why this is bad

The assistant did the reasonable thing with the available API surface and still got the wrong answer. That means this is not just a model mistake; the retrieval surface is materially hiding valid context.

Expected behavior

At least one of these should happen:

  1. sessions_history for a logical session key should follow reset/archive chains automatically and return prior fragments in order
  2. sessions_history should include metadata such as:
    • previousFragments
    • resetArchives
    • continuationOf
    • archivedMessagesAvailable: true
  3. system exec completion messages should carry enough provenance to resolve back to the originating transcript fragment / run / session
  4. a first-class tool/API should exist for "recover previous session fragment(s) for this logical session"

Repro sketch

  1. Start a long-running session that launches background exec jobs
  2. Trigger a prompt error / fetch failure / reset condition so the session rotates into *.jsonl.reset.*
  3. Let system exec completion messages arrive afterward
  4. In the fresh session, ask the assistant to continue
  5. Observe that sessions_history(sessionKey=...) may only show the fresh fragment and hide the archived one
  6. Observe that manual raw-file inspection can still recover the missing context

Proposed fix

Retrieval layer

  • Treat reset archives as part of the same logical session chain
  • Add an option like includeArchived=true / followResets=true to sessions_history
  • Prefer making this default for same-session recovery flows

Session metadata

  • Persist a durable chain pointer between fragments, e.g.:
    • previousSessionId
    • resetFromSessionId
    • logicalSessionKey
    • archiveReason

UX / tooling

  • When sessions_history is truncated and archived fragments exist, return explicit metadata saying so
  • Add a first-class recovery command/tool for locating prior fragments instead of requiring raw file spelunking

Event provenance

  • Exec completion notifications should include an origin reference to the session/run that launched them so they remain understandable after a reset

Acceptance criteria

  • Given a logical session that has been reset, sessions_history(sessionKey=...) can recover prior fragments without raw file inspection
  • If history is still truncated, the response explicitly says archived fragments exist and how to retrieve them
  • A user saying "continue" after a reset can be correctly resumed from tool-visible context
  • Exec completion notifications can be tied back to their originating work context even across session resets

Notes

This is distinct from normal truncation. The key bug is that valid context remained on disk but was effectively undiscoverable through the supported session tools, which directly caused a wrong user-facing answer.

extent analysis

Fix Plan

To address the issue, we will implement the following changes:

  • Retrieval layer: Update the sessions_history function to include an option like includeArchived=true / followResets=true to treat reset archives as part of the same logical session chain.
  • Session metadata: Persist a durable chain pointer between fragments, e.g., previousSessionId, resetFromSessionId, logicalSessionKey, and archiveReason.
  • UX / tooling: Return explicit metadata when sessions_history is truncated and archived fragments exist, and add a first-class recovery command/tool for locating prior fragments.
  • Event provenance: Include an origin reference to the session/run that launched exec completion notifications.

Code Changes

Here are some example code snippets to illustrate the changes:

# sessions_history function with includeArchived option
def sessions_history(sessionKey, limit=20, includeArchived=False):
    # ...
    if includeArchived:
        # Retrieve archived fragments and concatenate with current session
        archived_fragments = retrieve_archived_fragments(sessionKey)
        sessions = current_session + archived_fragments
    # ...

# Persisting durable chain pointer between fragments
class Session:
    def __init__(self, session_id, previous_session_id=None):
        self.session_id = session_id
        self.previous_session_id = previous_session_id
        # ...

# Returning explicit metadata when sessions_history is truncated
def sessions_history(sessionKey, limit=20, includeArchived=False):
    # ...
    if truncated and archived_fragments_exist:
        return {
            'truncated': True,
            'archivedFragmentsExist': True,
            'sessions': sessions
        }
    # ...

# First-class recovery command/tool for locating prior fragments
def recover_prior_fragments(sessionKey):
    # Retrieve archived fragments and return them
    archived_fragments = retrieve_archived_fragments(sessionKey)
    return archived_fragments

# Including origin reference to the session/run that launched exec completion notifications
class ExecCompletionNotification:
    def __init__(self, session_id, run_id, notification):
        self.session_id = session_id
        self.run_id = run_id
        self.notification = notification
        # ...

Verification

To verify that the fix worked, we can test the following scenarios:

  • Test that sessions_history with includeArchived=true returns the correct archived fragments.
  • Test that the durable chain pointer between fragments is correctly persisted.
  • Test that the UX/tooling changes correctly return explicit metadata when sessions_history is truncated and archived fragments exist.
  • Test that the event provenance changes correctly include an origin reference to the session/run that launched exec completion notifications.

Extra Tips

To prevent similar issues in the future, we should:

  • Regularly review and test the session retrieval layer to ensure it correctly handles edge cases.
  • Implement automated testing

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

At least one of these should happen:

  1. sessions_history for a logical session key should follow reset/archive chains automatically and return prior fragments in order
  2. sessions_history should include metadata such as:
    • previousFragments
    • resetArchives
    • continuationOf
    • archivedMessagesAvailable: true
  3. system exec completion messages should carry enough provenance to resolve back to the originating transcript fragment / run / session
  4. a first-class tool/API should exist for "recover previous session fragment(s) for this logical session"

Still need to ship something?

×6

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

Back to top recommendations

TRENDING