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

data gc skips version-count GC when no lifetime-expired data exists

Opened by keeb · 4/13/2026· Shipped 4/14/2026

Bug

swamp data gc (interactive mode) returns early with No expired data found. Nothing to clean up. and never runs version-count garbage collection. Resources configured with lifetime: infinite, gc: <N> accumulate unbounded versions even when swamp data gc is run.

Repro

  1. Have a model resource configured with lifetime: infinite and a finite version GC count (e.g. gc: 10).
  2. Write >N versions of that resource (I have 20,825 versions of one).
  3. Run swamp data gc.
  4. Observe: No expired data found. Nothing to clean up. — nothing is pruned, disk usage unchanged.

Confirmed: swamp data versions <model> <name> --json reports "total": 20825 and swamp data get <model> <name> --no-content shows Lifetime: infinite | GC: 10.

Root cause

In src/cli/commands/data_gc.ts around lines 72–78:

if (cliCtx.outputMode === "log" && !options.force && !options.dryRun) {
  const preview = await dataGcPreview(ctx, deps);
  if (preview.items.length === 0) {
    console.log("No expired data found. Nothing to clean up.");
    return;  // early return — never calls dataGc()
  }
  ...
}

dataGcPreview calls findExpiredData (src/domain/data/data_lifecycle_service.ts:182), which only finds lifetime-expired entries. It does not consider version-count overflow.

Phase 2 version GC (collectGarbage loop at data_lifecycle_service.ts:310-333) lives inside deleteExpiredData, which is only invoked by dataGc. When the preview returns empty, the early return skips that entirely.

Side effect: --force, --dry-run, and --json all bypass the preview branch, so version GC only works via those flags — which is surprising since the interactive default is the documented usage.

Suggested fix

The preview should also report models that have more versions than their GC policy allows (an "over-retention" category), and/or the early-return should be removed so Phase 2 always runs. Either way, the interactive default should not silently skip version-count GC.

Environment

  • swamp 20260206.200442.0-sha. (binary on target)
  • Repo: /opt/proxmox-manager (21 pulled extensions + 16 local workflows)
  • OS: Alpine Linux (running swamp inside a Debian-based docker container)
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 3 MOREPR_MERGEDSHIPPED

Shipped

4/14/2026, 12:55:38 AM

Click a lifecycle step above to view its details.

03Sludge Pulse
keeb assigned keeb4/14/2026, 12:22:34 AM

Sign in to post a ripple.