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

Relationships

#3566 doctor datastores decides v3 from the format key, so an override pointed at a v3 bucket runs the v2 contamination check and repair

Opened by stack72 · 10/16/2026

Problem

swamp doctor datastores decides whether a datastore is v3 from the config's format key, not from the format guard. An override config (the SWAMP_DATASTORE environment variable or --datastore) carries no format, because an override follows the bucket's marker (swamp-club#3534). Point such an override, with a namespace, at a v3 datastore on S3 or GCS and:

  • doctor datastores runs the v2 namespace-contamination check against the v3 prefix (src/cli/commands/doctor_datastores.ts:214);
  • doctor datastores --repair gets past the format-3 refusal (:352) and calls the extension's v2 repairNamespaceContamination({ dryRun: false }) against the v3 prefix.

The v3 layout (_control/, _blobs/, _litestream/) holds none of the v2 folders the repair moves, so the likely effect is a no-op. But a v2 write operation should never run against a v3 bucket at all, the invariant the rest of #3534 keeps and the extensions' format-3 refusal (swamp-club#3549) relies on.

Found by the CI adversarial review on swamp-club/swamp#3180 (MEDIUM) and the local adversarial review (LOW).

Fix

In both the check and the repair, run ensureSupportedDatastoreFormat (or read the guard's decision with datastoreEngineOf) and treat a v3 result as v3: skip the check, refuse the repair with the existing format-3 message. Add a test with an override config over a format-3 marker for each path.

02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS◉CLOSED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 1 MOREIMPLEMENTATION

Closed

10/16/2026, 11:18:49 PM

No activity in this phase yet.

03Sludge Pulse
stack72 assigned stack7210/16/2026, 10:54:56 PM
Editable. Press Enter to edit.

stack72 commented 10/16/2026, 11:06:24 PM

Triage note: the override scenario in the description cannot happen. An override config (the SWAMP_DATASTORE environment variable) never carries a namespace, since parseDatastoreEnvVar sets none, and doctor datastores passes no --datastore. So the check returns early on the missing namespace, and --repair stops at "Repair is only available for custom datastores with a namespace configured".

The reachable case is a .swamp.yaml extension datastore with a namespace and no format key whose bucket marker says 3: a hand edit, or a v2 config pointed at a prefix that is now v3. Every other command refuses that repo through the format guard; doctor did not consult the guard. The fix calls ensureSupportedDatastoreFormat in both paths, after the existing format 3 checks, and the tests use this reachable shape.

stack72 commented 10/16/2026, 11:18:49 PM

Correction: my earlier comment was wrong to call the no-format .swamp.yaml case reachable. It is not, and neither is the override case in the description. No swamp doctor datastores invocation runs the v2 namespace-contamination check or repair against a v3 datastore. Closing as not reachable.

Three reasons:

  1. The command runs the format guard on entry. The action calls resolveDatastoreForRepo (src/cli/commands/doctor_datastores.ts:611), which runs ensureSupportedDatastoreFormat before any deps are built. A .swamp.yaml extension datastore with a namespace and no format key over a format-3 marker is refused with DatastoreFormatMismatchError before the check or repair code runs.
  2. --repair is refused outright on v3. When the guard answers v3, the action throws at doctor_datastores.ts:616 ("--repair is not available for v3 datastores yet", from swamp-club#3279), before createRepairDeps.
  3. An override never carries a namespace. parseDatastoreEnvVar (src/cli/resolve_datastore.ts) sets no namespace on a SWAMP_DATASTORE config, and doctor datastores has no --datastore flag. So the check returns early on the missing namespace (doctor_datastores.ts:211); an override of a v3 bucket hits reason 2 anyway.

Test results: ministack S3, @swamp/s3-datastore 2026.10.16.5, v3 datastore created with datastore setup extension --format 3. Both binaries were compiled locally, the baseline at 2a5f732bd (no fix) and the branch with a guard-based fix:

  • .swamp.yaml with namespace team and format removed, then doctor datastores: both binaries refused with "The datastore config in .swamp.yaml says format 2, but the datastore's format marker says format 3 ... Nothing was changed."
  • Same repo with --repair -y: both binaries gave the same refusal.
  • SWAMP_DATASTORE override of the v3 bucket with --repair -y: both binaries refused with "--repair is not available for v3 datastores yet ... Nothing was changed."
  • After all runs the bucket held only p/_control/datastore-format.

The config.format === 3 checks inside createDoctorDatastoresDeps and createRepairDeps can only be reached by calling those factories directly, which skips the entry guard. The CLI never does that, so no fix ships for this issue.

Sign in to post a ripple.