Skip to main content
← Back to list
01Issue
BugClosedSwamp CLIPublic
AssigneesNone

Relationships

#2367 s3/gcs datastore: dirty-path overflow reconciliation can delete remote objects this mirror has not pulled yet

Opened by stack72 · 9/22/2026

Found while triaging swamp-club#2353. Extension-side (@swamp/s3-datastore and @swamp/gcs-datastore).

Problem

When more than DIRTY_PATHS_CAP (2000) distinct dirty paths are recorded, the extension sets bulkInvalidated and dirtyPathsOverflowed. The push then walks the whole cache and deletes every index entry that has no local file. The walk compares against the current remote index, so an object another writer pushed after this mirror's last pull has no local copy yet and is deleted.

The CLI flow is covered by the global lock plus the implicit pull before push. Serve and per-model locks (two-phase preparePush outside the global lock) can overlap, so a large GC under serve or concurrent workflows can delete another writer's fresh data.

Why it matters more now

The swamp-club#2353 core change sends two dirty paths per removed version (raw and metadata.yaml) instead of one version directory, so a GC reaches the cap at about 1000 versions instead of about 2000. Real repos hit this: the #2353 reporter's GC reclaimed 21,579 versions.

Direction (agreed with the extension work on #2353)

  • Near term, landing with #2353: in the bulk walk, treat each recorded dirty path that is missing locally as a precise delete, as the scoped walk does. This also fixes deletions currently lost when a GC shares a push cycle with a bare markDirty().
  • This issue: past the cap, move to chunked scoped pushes, not a whole-cache reconciliation against a remote index this mirror has not caught up with. Alternatively, only reconcile entries this mirror has synced.
02Bog Flow
✓OPEN○TRIAGED○IN PROGRESS◉CLOSED

Closed

9/22/2026, 9:23:53 PM

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.