prune never removes the encrypted database a backup left on the destination when its manifest upload failed #390

Open
opened 2026-10-14 09:52:33 +02:00 by clawbot · 0 comments
Collaborator

Severity: low

What is wrong: The metadata export uploads metadata/<key>/db.zst.age and then manifest.json.zst. When the second upload fails, or the run is killed between the two, the first stays on the destination and nothing removes it afterwards. prune reconciles the local record away and deletes the orphaned blobs, but deletes nothing under metadata/. snapshot remove hashes whatever identifier it is given, so the remote key remote info prints is reported as not found, and the human ID's local record is gone once prune has run. snapshot list does not show the directory, since it lists only keys with a manifest; remote info shows it as a snapshot with 0 blobs. Only remote nuke removes it. Each such run leaves a copy of the whole encrypted metadata database (the size of the local index: hundreds of MB for a large tree) on the destination for good, while the README says prune tidies up "everything that isn't needed".

Where: internal/snapshot/snapshot.go uploadSnapshotArtifacts (database before manifest); internal/vaultik/prune.go Prune and PruneBlobs (nothing under metadata/ is ever deleted); internal/vaultik/snapshot.go findSnapshotToRemove (always hashes the identifier).

How it was shown: file:// destination. After one good backup, a directory was planted at the manifest path of the next run, so its manifest upload failed after db.zst.age had been uploaded (exit 1). prune --force then printed Removing stale local record, Deleted 1 blob(s), exit 0; metadata/786ec3.../db.zst.age was still there, and still there after the next day's backup and another prune. snapshot list omits it; remote info lists it with 0 blobs; snapshot remove --force with its key says snapshot not found.

Definition of done

  • prune deletes, under metadata/, a directory that has no manifest.json.zst, that no local snapshot record claims, and that a backup in progress cannot be writing (older than the grace period chosen for #387, or not leased), and reports what it removed; or snapshot remove accepts a remote key as verify and restore do, and the README tells the user to run it for a key remote info shows with 0 blobs.
  • A test covers a metadata/ directory holding only db.zst.age.

Model: fable-5-1

**Severity:** low **What is wrong:** The metadata export uploads `metadata/<key>/db.zst.age` and then `manifest.json.zst`. When the second upload fails, or the run is killed between the two, the first stays on the destination and nothing removes it afterwards. `prune` reconciles the local record away and deletes the orphaned blobs, but deletes nothing under `metadata/`. `snapshot remove` hashes whatever identifier it is given, so the remote key `remote info` prints is reported as not found, and the human ID's local record is gone once prune has run. `snapshot list` does not show the directory, since it lists only keys with a manifest; `remote info` shows it as a snapshot with 0 blobs. Only `remote nuke` removes it. Each such run leaves a copy of the whole encrypted metadata database (the size of the local index: hundreds of MB for a large tree) on the destination for good, while the README says `prune` tidies up "everything that isn't needed". **Where:** `internal/snapshot/snapshot.go` `uploadSnapshotArtifacts` (database before manifest); `internal/vaultik/prune.go` `Prune` and `PruneBlobs` (nothing under `metadata/` is ever deleted); `internal/vaultik/snapshot.go` `findSnapshotToRemove` (always hashes the identifier). **How it was shown:** `file://` destination. After one good backup, a directory was planted at the manifest path of the next run, so its manifest upload failed after `db.zst.age` had been uploaded (exit 1). `prune --force` then printed `Removing stale local record`, `Deleted 1 blob(s)`, exit 0; `metadata/786ec3.../db.zst.age` was still there, and still there after the next day's backup and another `prune`. `snapshot list` omits it; `remote info` lists it with 0 blobs; `snapshot remove --force` with its key says `snapshot not found`. **Definition of done** - `prune` deletes, under `metadata/`, a directory that has no `manifest.json.zst`, that no local snapshot record claims, and that a backup in progress cannot be writing (older than the grace period chosen for https://git.eeqj.de/sneak/vaultik/issues/387, or not leased), and reports what it removed; or `snapshot remove` accepts a remote key as `verify` and `restore` do, and the README tells the user to run it for a key `remote info` shows with 0 blobs. - A test covers a `metadata/` directory holding only `db.zst.age`. Model: fable-5-1
Sign in to join this conversation.