Skip to main content
← Back to list
01Issue
BugShippedSwamp CLI
Assigneesstack72

Relationships

#603 `vault put` inside workflow steps still acquires global `.datastore.lock` after #382

Opened by bixu · 6/9/2026· Shipped 6/9/2026

Summary

swamp vault put invoked from a workflow step still acquires the global .datastore.lock rather than a vault-scoped lock, despite #382 shipping. When any other process holds the global lock (e.g. a concurrent model method push), the vault put step times out and fails the entire workflow run.

Reproduction

  1. Use the S3 datastore.
  2. Define a workflow with a step that runs vault put against a vault.
  3. Trigger the workflow while another swamp process is pushing to the datastore (e.g. a scheduled model method run on the same or different machine).
  4. The vault put step fails with:
LockTimeoutError: Lock ".datastore.lock" held by <user>@<host> (pid <pid>) — timed out after 60457ms
    at S3Lock.acquire (.swamp/datastore-bundles/<hash>/s3.js:53092:15)
    at async registerDatastoreSyncNamed (src/infrastructure/persistence/datastore_sync_coordinator.ts:285:7)
    at async registerDatastoreSync (src/infrastructure/persistence/datastore_sync_coordinator.ts:238:3)
    at async <repo_context.ts>:528:7
    at async Command.<anonymous> (src/cli/commands/vault_put.ts:163:38)

Root cause

vault_put.ts:163 calls requireInitializedRepo(), which unconditionally acquires the global .datastore.lock via registerDatastoreSync() at repo_context.ts:528 with datastoreGlobalLockOptions() at line 505. This is the same code path #382 identified.

requireInitializedRepoReadOnly() exists (documented at line 459–460 as the read-only alternative), but vault put does need to write — just to a specific vault path, not the full datastore. A vault-scoped lock (as suggested in #382) would avoid this contention.

Environment

  • swamp 20260608.183926.0-sha.b6b4d83d
  • macOS, ARM64
  • Datastore: @swamp/s3-datastore
  • Workflow invoked vault put as part of a multi-step key rotation workflow

Relationship to existing issues

  • Follow-up to #382 (shipped) — vault put was listed as an affected command but the global lock path is unchanged in the current source.
  • Related to #520 (triaged) — same lock contention family, but this is specifically the global .datastore.lock acquired by vault put, not per-model locks under concurrent access.
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 9 MOREREVIEW+ 3 MOREPR_MERGED+ 1 MORECONTRIBUTOR_NOTIFIED

Shipped

6/9/2026, 6:38:40 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack726/9/2026, 12:55:49 PM
Editable. Press Enter to edit.

stack72 commented 6/9/2026, 6:38:49 PM

Thanks @bixu for reporting this! The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.