#4853·gastown

dolt_backup patrol queries dolt_remotes instead of dolt_backups — backups silently never run

Author: schmackaCreated Sep 13, 2026Updated Sep 13, 2026
Labelsstatus/needs-triage

Summary

The daemon's dolt_backup patrol enumerates backup-eligible databases by querying dolt_remotes, but dolt backup add writes to dolt_backups — a different system table. The query returns empty, the patrol logs no databases with backup remotes found, and no backup ever runs.

This is fail-open: the log line reads like a normal no-op, nothing escalates, and gt reports no error. A town can run for days believing it is backed up. Ours did — 46 hours, five databases, zero backups, no warning.

Repro

Any town whose databases were configured with dolt backup add:

bash
$ cd <town>/.dolt-data/hq
$ dolt backup -v
backup_export file:///Users/me/gt/.beads/backup {}

$ dolt sql -q 'SELECT name FROM dolt_remotes'
(empty)

$ dolt sql -q 'SELECT name FROM dolt_backups'
+---------------+
| name          |
+---------------+
| backup_export |
+---------------+

Then watch the daemon:

bash
$ grep dolt_backup daemon/daemon.log | tail -3
2026/09/13 08:28:29 dolt_backup: no databases with backup remotes found
2026/09/13 09:49:00 dolt_backup: no databases with backup remotes found
2026/09/13 10:20:37 dolt_backup: no databases with backup remotes found

All five databases in this town had backup_export configured. The patrol found none of them, on every cycle, for days.

Cause

The gt binary contains the literal query:

USE `%s`; SELECT name FROM dolt_remotes LIMIT 1

Dolt keeps remotes and backups in separate tables. dolt backup add <name> <url> populates dolt_backups; dolt remote add populates dolt_remotes. A database can have a backup configured and no remote at all — which is the normal shape for a backup-only setup, and is what gt's own docs steer users toward.

Suggested fix

Enumerate from dolt_backups (or union both) when selecting databases for the backup patrol.

Separately, and arguably more important than the query itself: no databases with backup remotes found should not be a routine INFO line. If a town has databases and none are backup-eligible, that is a misconfiguration worth surfacing, not a quiet skip. Backups are the one subsystem whose whole purpose is to be there after everything else has failed; it should be the loudest thing in the daemon, not the quietest.

Related, same fail-open shape in the same subsystem

jsonl_git_backup: git repo /Users/me/.dolt-archive/git does not exist, skipping

A missing archive directory is also treated as a skip rather than a misconfiguration to surface. Same consequence: silent, indefinite, no backups. Both paths would benefit from escalating instead of logging and continuing.

This is the same family as #4632 (gt hook serialising a failed read as Nothing on hook with rc=0) — an error rendered as a normal empty result.

Environment

  • gastown v1.1.0 (Homebrew)
  • beads 1.2.2 (Homebrew)
  • dolt 2.3.3
  • macOS (Darwin 25.5.0, arm64)
  • 5 databases, all with backup_export targets configured

Workaround

Calling DOLT_BACKUP('sync', ...) per database directly works and is unaffected by the enumeration bug:

bash
cd <town>/.dolt-data/<db>
dolt sql -q "CALL DOLT_BACKUP('sync','backup_export')"

We now run this hourly from launchd, logging per target and exiting nonzero on failure, and verified it by restoring a backup into a scratch directory and comparing row counts and content against live.