Skip to content

[Bug]: Daily session reset regresses #57020 — sessionFile not rotated #78607

@nailujac

Description

@nailujac

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

Daily session reset updates sessionId in sessions.json but the previous sessionFile path keeps being reused indefinitely. The transcript JSONL never rotates, so context grows across days/weeks. This is a regression of #57020 (closed 2026-04-25) — the same bug returned in v2026.4.27 (or in one of v2026.4.25 → v2026.4.27) and persists through v2026.5.4. The fix code path in resolveAndPersistSessionFile() still exists but is no longer effective for sessions that already had a sessionFile persisted before the reset boundary.

Steps to reproduce

  1. Start a fresh session under v2026.4.27+ (or upgrade an existing per-channel-peer/main session at any point during this version range).
  2. Chat normally over multiple days, crossing several daily reset boundaries (default 4AM).
  3. Inspect sessions.json (~/.openclaw/agents//sessions/sessions.json) for the relevant sessionKey (e.g. agent:main:main).
  4. Compare:
    • sessions.json → sessionId
    • sessions.json → sessionFile basename
  5. Observe the IDs no longer match: sessionId is recent, but sessionFile points to a transcript JSONL whose header timestamp (head -1) predates sessionId by days.

Expected behavior

On daily reset, sessionId rotates AND a new sessionFile path is generated so a fresh JSONL transcript is created. The old transcript should be archived (per resetArchiveRetention) and the new one used from then on. This was the behavior observed after the fix for #57020 landed (between 2026-04-25 and 2026-04-30 in our environment).

Actual behavior

sessionId rotates daily (visible in sessions.json — updatedAt advances, sessionStartedAt advances) but sessionFile is reused indefinitely. The same JSONL keeps growing across weeks — in our case 685a51f7-...jsonl, header timestamp 2026-04-30T18:04:00Z, still the active sessionFile on 2026-05-06 with sessionId=63b16647-... (which has no matching JSONL with that name on disk).

Code path inspection (dist/session-file-BwLxTARg.js — bundled in 2026.5.4):

const baseEntry = params.sessionEntry ?? sessionStore[sessionKey] ?? {...};
const shouldReusePersistedSessionFile = baseEntry.sessionId === sessionId;

When the daily reset triggers, baseEntry comes from sessionStore[sessionKey] which ALREADY has the new sessionId persisted (the reset wrote it before this resolver runs). So baseEntry.sessionId === sessionId is always true on the path that triggers the reset, and the existing sessionFile is reused. The fix that landed for #57020 still exists in code but no longer gets exercised by the reset path because something upstream now writes the new sessionId into sessionStore before calling this resolver.

OpenClaw version

2026.5.4 (regression introduced somewhere between 2026.4.25 and 2026.4.27)

Operating system

Ubuntu 24.04 (Oracle Cloud ARM64)

Install method

npm global

Model

anthropic/claude-opus-4-7

Provider / routing chain

openclaw -> anthropic

Additional provider/model setup details

session config in openclaw.json:
{
"session": {
"dmScope": "main"
}
}

No explicit session.reset config — relying on the documented default (daily at 4AM local Europe/Madrid, gateway local timezone).

Logs, screenshots, and evidence

# sessions.json entry for the affected session:
sessionKey: agent:main:main
  sessionId: 63b16647-ea0c-4a22-808b-ce616326b445   (updated recently)
  sessionFile: /home/ubuntu/.openclaw/agents/main/sessions/685a51f7-7adf-48b1-89ca-d3ab86dd6e0f.jsonl
  sessionStartedAt: 1778044514861   (2026-05-06)
  compactionCount: 11

# Transcript header — predates sessionId by 6 days, 11 compactions later still
# the active file:
$ head -1 /home/ubuntu/.openclaw/agents/main/sessions/685a51f7-7adf-48b1-89ca-d3ab86dd6e0f.jsonl
{"type":"session","version":3,"id":"685a51f7-7adf-48b1-89ca-d3ab86dd6e0f","timestamp":"2026-04-30T18:04:00.324Z","cwd":"/home/ubuntu/.openclaw/workspace"}

$ ls -la /home/ubuntu/.openclaw/agents/main/sessions/685a51f7-7adf-48b1-89ca-d3ab86dd6e0f.jsonl
-rw-rw-r-- 1 ubuntu ubuntu 6889076 May  6 19:38 (~6.6 MB, growing)

# No JSONL exists with the current sessionId name:
$ ls /home/ubuntu/.openclaw/agents/main/sessions/63b16647-* 2>&1
ls: cannot access ...: No such file or directory

# Gateway version progression on this machine while the session never rotated
# its sessionFile:
- 2026-04-25 — 2026.4.21
- 2026-04-28 — 2026.4.23, 2026.4.25
- 2026-04-30 19:51 — 2026.4.27 (last upgrade with normal-looking session creation)
- 2026-05-05/06 — 2026.5.4 (current)

# The 30-Apr 19:51 startup is the last time a fresh sessionFile was created for
# this session. Multiple reset boundaries since (>= 6 daily resets) without

Impact and severity

Affected: any session that had a sessionFile persisted in the store before its first daily reset under v2026.4.27+ (i.e., effectively all long-lived sessions on upgraded environments).

Severity: Medium-High — sessions never truly reset, context grows indefinitely across days/weeks. Compaction (we have 11 so far) mitigates active in-context size but the on-disk transcript and the conversation history that compaction reads from grow unboundedly. This regresses #57020 which had previously fixed this exact behavior.

Frequency: Every daily reset boundary, on every long-lived session.

Workaround verified: manual /reset (or /new) triggers a full session reset including sessionFile rotation. Same workaround that #57020 documented.

Additional information

This is a regression of:

The fix code path is still present in v2026.5.4 (dist/session-file-BwLxTARg.js → resolveAndPersistSessionFile(): shouldReusePersistedSessionFile = baseEntry.sessionId === sessionId), but it is no longer effective because the reset path appears to update sessionStore[sessionKey].sessionId BEFORE calling this resolver, so the resolver always sees baseEntry.sessionId matching the new sessionId and skips the rotation guard.

Likely root cause locations to check:

  • src/config/sessions/init.ts (or equivalent) — initSessionState() / daily-reset trigger: check whether it now writes the new sessionId into sessions.json before invoking resolveAndPersistSessionFile, instead of letting the resolver see the old (mismatching) sessionId in baseEntry.
  • The original fix design assumed baseEntry.sessionId reflects the PRE-reset state when the resolver is called. That invariant no longer holds.

Suggested fix shapes (any of):

  1. Pass the previous sessionId explicitly into resolveAndPersistSessionFile so the guard can detect a reset regardless of what's already in baseEntry.
  2. Have the reset path clear baseEntry.sessionFile (set to undefined) before calling the resolver, like the original fix proposal suggested.
  3. Have initSessionState detect "reset boundary crossed" and pass an explicit isReset=true flag through to the resolver so it can force-rotate sessionFile.

Window of regression on our environment:

  • Last known good: v2026.4.25 or early v2026.4.27 (last sessionFile creation: 30-Apr 18:04 UTC, ~1h45m before the v2026.4.27 systemd unit restart).
  • Confirmed broken: v2026.4.27 runtime onwards through v2026.5.4 (no rotation for 6 consecutive daily reset boundaries).

I will trigger a manual /reset locally as a workaround once this is filed.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingregressionBehavior that previously worked and now fails

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions