From b9ebe6f3af41ebdf3f9ed4d69c5b097cc4e26c85 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Jul 2026 17:19:34 +0700 Subject: [PATCH] Abort merge when backupMmdb fails (codex #3, High) backupMmdb() could return an error but the code still proceeded into mergeMmdb(), which truncates the canonical mmdb. With no backup, a later merge/reload failure left the file corrupt and unrecoverable on restart. Now we skip the rebuild entirely when the backup fails, and rollBackMmdb no longer takes the backup error (the only failure path returns early). Co-Authored-By: Claude --- internal/services/db_updater/main.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/internal/services/db_updater/main.go b/internal/services/db_updater/main.go index 7418a41..66072e2 100644 --- a/internal/services/db_updater/main.go +++ b/internal/services/db_updater/main.go @@ -44,9 +44,18 @@ func fetchDbs() { // restart (which then fails to open the empty file). Back the file up // first so we can restore it on failure. backup, backupErr := backupMmdb() + if backupErr != nil { + // We could not back up the current canonical mmdb. Do NOT proceed: + // mergeMmdb() truncates the canonical file before writing, and with + // no backup a later merge/reload failure would leave it corrupt + // (unrecoverable on restart). Keep serving the current DB and let + // the next run retry. + log.Err(backupErr).Msg("Failed to back up mmdb, skipping rebuild") + return + } if err := mergeMmdb(); err != nil { log.Err(err).Msg("Failed to merge mmdb") - rollBackMmdb(backup, backupErr) + rollBackMmdb(backup) return } @@ -55,7 +64,7 @@ func fetchDbs() { log.Err(err).Msg("Failed to reload mmdb") // Reload failed on the newly merged file: restore the previous // canonical mmdb so we keep serving known-good data. - rollBackMmdb(backup, backupErr) + rollBackMmdb(backup) return } @@ -103,10 +112,10 @@ func backupMmdb() (string, error) { // rollBackMmdb restores the canonical mmdb from backup (if any) and deletes // the etag files so the next cron run re-downloads and retries the merge. -func rollBackMmdb(backup string, backupErr error) { - if backupErr != nil { - log.Err(backupErr).Msg("No mmdb backup available; cannot restore") - } else if backup != "" { +// backup is "" on a first-ever build (no canonical file existed to back up), +// in which case there is nothing to restore. +func rollBackMmdb(backup string) { + if backup != "" { if err := osx.Copy(backup, configs.MmdbDbFile); err != nil { log.Err(err).Msg("Failed to restore mmdb backup") } else {