Repository navigation
Replies: 1 comment
|
Hi! I think session discovery should be independent from successfully parsing the complete session history. If the session metadata can be enumerated but the event log is damaged, the UI should still display an entry identifying the session as unreadable or corrupted. That entry could offer safe diagnostic actions such as exporting the original raw data, viewing the parsing error, and creating a backup before attempting repair. I would avoid automatically rewriting or deleting damaged sessions during normal list loading. A useful regression test would create a session with a valid metadata record and a corrupted event log, then verify that it remains visible and recoverable through the UI. This would prevent data corruption from becoming an apparently missing-session problem. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
A corrupt session log disappears from the session list with no error and no way back
App: DeepSeek Harness Desktop
0.2.1-rc.5(Windows,app.asarof 2026-10-29)Observed: 2026-11-03
Symptom
One session stopped opening. The GUI showed:
After a restart the session was gone from the list entirely — no error, no toast, no entry, nothing. The directory was still on disk, complete and readable:
So from the user's point of view the conversation was silently deleted. It was not.
What actually broke (two independent layers)
Layer 1 — an event was appended before its step was open
A third-party plugin appends a
developer/messagefrom theagent/pre-stepwaterfall. That hook runs before the loop writesstep/start:dsh-agent-loop/lib/index.js:910—await this.dispatch.waterfall("agent/pre-step", …)dsh-agent-loop/lib/index.js:971—this.session.append("step/start", …), only after the waterfall returnsSo the plugin's message is written while no step is open. The resulting log has that order:
Relationships.requireStep(dsh-session-format-v3-to-v4/lib/index.js:574) rejects exactly this on load:This is deterministic, not a race. Every time that plugin's rule fires, the message lands before
step/start.Layer 2 — the damage is only discovered on the next open
session.append(dsh-session/lib/index.js:1518) snapshots the data and callsvalidateSessionEventData, which validates shape only. Nothing checks turn/step relationships at write time. The write succeeds, the process keeps running, and the log is already unloadable.On the next start,
listArtifactsdiscovers the error and simply drops the entry, which is why the list shows nothing instead of a warning. There is no "file is corrupt, try to recover" path in the UI, andrecoverablereading mode still throws on aturn/endboundary.This is reproducible data, not one bad coincidence
Scanning all 164 local session logs, this exact pattern appears 3 times (the only 3 injections that plugin ever made):
session-f1f7574c-…developer/messageseq 3699 →step/startseq 3700session-f1f7574c-…developer/messageseq 4183 →step/startseq 4184session-43ed7817-…developer/messageseq 334 →step/startseq 335The first two were repaired by hand on 2026-11-02 22:56 (a copy of the pre-repair log is still next to the live one as
session.v4.jsonl.zstd.bak-repair-2026-11-02T14-56-15-764Z, and it still showsdeveloper/messagesitting beforestep/start). The third was never repaired, so it became invisible.Two of three were repaired by luck, not by the app. The user only sees the one that was not.
Repair that worked
Swapping the two adjacent events and exchanging their
seqvalues makes the log valid again (deleting a line is not an option —planSurfaceEventrequires contiguousseq). Verified against the app's own validator:One more trap for anyone repairing by hand: the log must be re-compressed as two Zstandard frames — the header line alone in frame 1, everything else in frame 2. A single-frame re-compression passes
validateStoredEventsand is then silently rejected byassertZstdHeaderFrame(dsh-session-persistence-jsonl/lib/index.js:2298):Suggested fixes, in order of value
session.appendshould reuse the sameRelationshipsfold the loader uses and throw at the write site. The bad event would then fail inside the culprit plugin, be caught by its own try/catch, and the log would stay loadable. This alone would have prevented all three incidents.listArtifactsshould surface the session as "damaged" with the exact reason and the log path, and keep it in the list. A user can then copy the file out before it is lost.dsh session repair <id>would turn "conversation is gone" into "conversation is back".recoverableactually recoverable. Right now it still throws on aturn/endboundary, so the mode does not help the case it is named for.Environment / evidence
0.2.1-rc.5,app.asar182,766,714 bytes, mtime 2026-10-29.developer/message,source.kind = "dsh-lead-router",form: instructions, time 1793697442683 (2026-11-03 17:17:22 UTC+8).validateStoredEvents(0 further failures), so this is not a general storage problem — it is specifically the "message appended before its step" case that nothing guards.All reactions