You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Running two hosts against the same $DSH_HOME makes storages/ state silently regress: data written by one host disappears when the other writes.
Observed on Windows with DSH 0.1.5-rc.2. The symptom that surfaced it: 142 of 235 sessions were never registered to their workspace — the workspace listed 29 session ids, all created inside a three-day window; every session created after that window was missing, and nothing was ever reported to the user.
This is not a third-party deployment mistake
The shipped desktop host derives its paths from a home documented as shared with npm-installed dsh:
// apps/desktop/src/paths.ts/** @param dshHome - Harness home shared with npm-installed dsh. */exportfunctionresolveDesktopPaths(dshHome: string=resolveDshHome()): DesktopPaths{return{profile: join(dshHome,'profiles','desktop'),lock: join(dshHome,'profiles','desktop','lock'),// …}}
It owns profiles/desktop exclusively — with its own lock — but not storages/. So the desktop host running alongside dsh web (or an npm-installed dsh) shares the same storage directory: the collision is reachable inside the shipped product line, not only to downstream integrations.
Why it is silent
packages/storage/storage-json writes a whole unit by atomic replace, and its module comment states the assumption:
Rename is an atomic replace on POSIX and on Windows …writer per process and last-write-wins is correct.
A second process holding a stale in-memory snapshot wins the race and overwrites the other's writes. storage-domain serializes writes within one process only, so nothing detects the conflict.
packages/storage/storage-sqlite does not help either — its README says:
No busy-wait or retry policy — a competing connection holding a write lock rejects the operation immediately instead of waiting; the domain layer's write chain serializes writes within one process, and cross-process coordination is out of scope.
There is also a client-side amplifier: the failure only reaches console.warn (packages/client/ui-workspace/src/client/navigation.ts, 'new session failed:'), so the user never sees an error.
Why a backend-level fix cannot cover it
The update window spans the whole read-modify-write cycle, not a single write. An application-level holder reads the unit, mutates in memory, and writes the whole unit back later. A lock inside a backend cannot cover that window, which is why swapping backends does not fix it.
Affected $DSH_HOME state observed here:
Path
Effect
storages/workspace.json
workspace membership lost (confirmed)
storages/memory.json
cross-session memory lost (same full-document write pattern)
storages/query-log.json
counters drift
plugin-owned stores under ~/.dsh/*.json
favorites / state lost
Sessions and profiles are not affected when the hosts use separate session roots — only storages/ is shared by default.
Reproduction sketch
Start two hosts against one DSH_HOME (for example dsh --profile web, plus a second host with its own profile but the same home).
In host A, create a session bound to a workspace.
Let host B perform any write to the same storage unit.
The session from step 2 is no longer accounted: the UI shows it under "ungrouped" and the storage file no longer lists it.
What we would like
Any one of:
Cross-process coordination in storage-domain — a lock around the unit lifecycle, or a version check that rejects a stale whole-unit write instead of applying it.
A stale-write detector — for example a mutation counter per unit, so a writer can tell its snapshot is stale and report it rather than overwrite.
If neither is in scope soon, document the constraint: "one writer per DSH_HOME; concurrent hosts require separate homes", and let a host detect and refuse that configuration instead of losing data silently.
Option 3 alone would already remove the silent part, which is the worst property here.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
What happens
Running two hosts against the same
$DSH_HOMEmakesstorages/state silently regress: data written by one host disappears when the other writes.Observed on Windows with DSH
0.1.5-rc.2. The symptom that surfaced it: 142 of 235 sessions were never registered to their workspace — the workspace listed 29 session ids, all created inside a three-day window; every session created after that window was missing, and nothing was ever reported to the user.This is not a third-party deployment mistake
The shipped desktop host derives its paths from a home documented as shared with npm-installed
dsh:It owns
profiles/desktopexclusively — with its own lock — but notstorages/. So the desktop host running alongsidedsh web(or an npm-installeddsh) shares the same storage directory: the collision is reachable inside the shipped product line, not only to downstream integrations.Why it is silent
packages/storage/storage-jsonwrites a whole unit by atomic replace, and its module comment states the assumption:A second process holding a stale in-memory snapshot wins the race and overwrites the other's writes.
storage-domainserializes writes within one process only, so nothing detects the conflict.packages/storage/storage-sqlitedoes not help either — its README says:There is also a client-side amplifier: the failure only reaches
console.warn(packages/client/ui-workspace/src/client/navigation.ts,'new session failed:'), so the user never sees an error.Why a backend-level fix cannot cover it
The update window spans the whole read-modify-write cycle, not a single write. An application-level holder reads the unit, mutates in memory, and writes the whole unit back later. A lock inside a backend cannot cover that window, which is why swapping backends does not fix it.
Affected
$DSH_HOMEstate observed here:storages/workspace.jsonstorages/memory.jsonstorages/query-log.json~/.dsh/*.jsonSessions and profiles are not affected when the hosts use separate session roots — only
storages/is shared by default.Reproduction sketch
DSH_HOME(for exampledsh --profile web, plus a second host with its own profile but the same home).What we would like
Any one of:
storage-domain— a lock around the unit lifecycle, or a version check that rejects a stale whole-unit write instead of applying it.DSH_HOME; concurrent hosts require separate homes", and let a host detect and refuse that configuration instead of losing data silently.Option 3 alone would already remove the silent part, which is the worst property here.
All reactions