Backup Job Succeeded but the File Is Empty

Short answer

A backup job can exit with code 0 and still produce a useless artifact. This happens when the dump command fails silently, credentials are missing, stderr is ignored, or a file is created by redirection before any real data is written to it. A successful exit code tells you the process ran — it does not tell you the backup is restorable.

Why empty backups happen

Minimum backup checks

Before trusting a backup, verify:

  1. File exists at the expected path and filename pattern.
  2. File size is above a sane threshold — not just non-zero, but consistent with the size of prior backups.
  3. Modified within the expected window — a stale backup from three days ago passing an “exists” check is not a passing backup.
  4. Compression integritygzip -t or equivalent passes without error.
  5. Dump has the expected header or format — a SQL dump should start with the expected -- MySQL dump or PGDMP header, not be empty or truncated mid-statement.
  6. Periodic restore test — the strongest guarantee is restoring the backup to a scratch database and running a basic query against it.

A better pattern

# Write to a temp file first
pg_dump mydb > /backups/mydb.sql.tmp

# Validate before promoting
if [ -s /backups/mydb.sql.tmp ] && head -c 5 /backups/mydb.sql.tmp | grep -q "PGDMP\|--"; then
  mv /backups/mydb.sql.tmp /backups/mydb.sql
else
  echo "backup validation failed: empty or malformed dump" >&2
  exit 1
fi

The core idea: never let an unvalidated file overwrite your last known-good backup. Validate first, promote (move/rename) second, and alert loudly if validation fails.

Where Night Watchman fits

Night Watchman is built for exactly this failure mode in file-artifact backup jobs. Instead of trusting the cron process’s exit code, it checks the backup artifact itself after the job runs — file existence, freshness, size relative to history, and format — and escalates an evidence dossier (file path, byte count, timestamp, and what was expected vs. observed) rather than a bare pass/fail. It does not auto-fix or re-run your backup job; it surfaces what it found so a human can decide.

FAQ

Why does my backup job show success but the file is empty?

Because “success” usually means the shell process exited with code 0, which only reflects the last command in a pipeline or the outer script — not whether the actual dump command produced valid data.

How do I check if a backup is restorable without doing a full restore?

At minimum check file size against history and confirm the file’s header matches the expected dump format. For real confidence, periodically restore to a scratch database.

Should I alert on backup size instead of just existence?

Yes. A file that exists but is 10x smaller than yesterday’s backup is a stronger warning sign than a missing file, and it’s easy to miss without a size check.

Try Night Watchman

Install from the public repository:

curl -fsSL https://raw.githubusercontent.com/ssddee-dev/code-batman/main/install.sh | bash
cd ~/night-watchman
.venv/bin/python -m watchman.setup