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

Relationships

#834 fix: datastore sync --push deletes the namespace registration manifest (canonical namespace flow un-registers itself)

Opened by anthony · 6/26/2026· Shipped 6/26/2026

Summary

swamp datastore sync --push deletes the {namespace}/.namespace.json registration manifest from the bucket. registerNamespace() writes the manifest directly to the object store and never materializes it into the local cache, so a namespace-scoped push treats it as a remote orphan and removes it. The canonical multi-repo flow — namespace set -> namespace migrate --confirm -> sync --push — therefore silently UN-registers the namespace it just registered: namespace list returns empty and repoId conflict-detection is defeated.

This is NOT "namespace set doesn't call registerNamespace" — it does, correctly (per #542). The manifest is written by set, survives migrate (local-only), and is destroyed by the following push.

Repro (minimal; @swamp/gcs-datastore; isolated throwaway prefix)

swamp repo init
swamp extension pull @swamp/gcs-datastore
swamp datastore setup extension @swamp/gcs-datastore --config '{"bucket":"B","prefix":"P","projectId":"..."}'   # NO namespace
swamp datastore namespace set ns
#   -> gs://B/P/ns/.namespace.json EXISTS
swamp datastore namespace migrate --confirm
#   -> manifest still EXISTS (migrate is local-only; prints "run sync --push")
swamp datastore sync --push
#   -> "Pushed 1 files"; gs://B/P/ns/.namespace.json is now GONE
swamp datastore namespace list   # -> "No namespaces registered in this datastore"

Control: set -> push WITHOUT an intervening migrate pushes 0 files and does NOT delete the manifest. The deletion happens specifically during a push that actually syncs the namespace subtree (checkpointed: manifest present after set and after migrate, absent immediately after push).

Root cause (hypothesis)

registerNamespace (datastores/gcs.ts) writes {namespace}/.namespace.json straight to the bucket; it is not part of the local cache tree. The namespace-scoped push reconciles the remote {namespace}/ subtree against the local cache and deletes remote objects with no local counterpart — including the manifest. Push should treat .namespace.json (and other reserved manifest/index files like .datastore-index.json/.catalog-export.json) as protected, not orphans.

Impact

  • The documented canonical flow (set -> migrate -> sync --push, manual "Add a namespace to an existing repository") destroys its own registration.
  • namespace list -> empty; foreign-catalog discovery (listNamespaces) cannot enumerate the namespace.
  • repoId conflict-detection is inert: a second repo can claim the same namespace undetected.
  • Data isolation (driven by the .swamp.yaml namespace, not the manifest) still works, so this is SILENT — the layout looks correct while registration is gone. Re-creating the manifest by hand is only temporary: the next sync --push deletes it again.

Environment

swamp 20260626.005336.0-sha.f302d18e; @swamp/gcs-datastore. Confirmed on a live GCS datastore and reproduced twice in clean throwaway prefixes.

#547 (extensions implement registerNamespace), #542 (namespace set registers manifests), #559 (setup-with-namespace-config path) — this is a distinct sink: push deletes what set wrote.

Upstream repository: https://github.com/systeminit/swamp-extensions

Environment

  • Extension: @swamp/gcs-datastore@2026.06.24.1
  • swamp: 20260626.005336.0-sha.f302d18e
  • OS: linux (x86_64)
  • Deno: 2.8.3
  • Shell: /bin/zsh
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 3 MOREPR_MERGED+ 1 MORECONTRIBUTOR_NOTIFIED

Shipped

6/26/2026, 5:40:21 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack726/26/2026, 4:04:18 PM
Editable. Press Enter to edit.

stack72 commented 6/26/2026, 5:40:29 PM

Thanks @anthony 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.