fix(backup): don't fail volume backups on warning-level tar exits #18

Merged
james merged 1 commit from fix/volume-backup-tar-warning-exit into main 2026-07-30 15:42:41 +00:00
Owner

Problem

Odoo's volume backup failed most attempts:

Volume backup command failed (exit 1): tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets
tar: /var/log/odoo/odoo-server.log: file changed as we read it

tar exits 1 for warning-level conditions ("some files differ") and reserves 2
for fatal errors. Odoo appends to its server log constantly, and that log lives inside a
backed-up mount — so tar noticed the file growing under it and exited 1.

StreamingCommandExecutor treated every non-zero exit as fatal, so the backup was
discarded even though the archive was complete and restorable. Failures were intermittent
because they depended on whether the app happened to write during tar's read window —
hence "most" attempts, not all.

Fix

Tolerate warning-level tar exits — but not on the exit code alone. BusyBox tar exits 1
for genuine errors too:

$ docker run --rm busybox sh -c 'tar -czf - /nonexistent; echo exit=$?'
tar: /nonexistent: No such file or directory
tar: error exit delayed from previous errors
exit=1

So an exit of 1 is accepted only when every stderr line matches a known-benign warning
(file changed as we read it, File removed before we read it, socket ignored,
leading-slash notices). Anything unrecognised fails closed.

  • tar's exit semantics live in VolumeBackupStrategy, which already owns the tar command
  • StreamingCommandExecutor takes an injected warning_filter:; its default is unchanged,
    so database dumps still fail on any non-zero exit
  • Both volume paths fixed — in-container tar and the host-side docker cp fallback carried
    the same defect

Verification

Not just specs. Reproduced the real condition with a Debian container appending to a 30MB
log on a mounted volume:

Scenario Result
Pre-fix, 3 runs 3/3 failed with the exact reported error
Post-fix, 5 runs 5/5 succeeded
Archive integrity gzip -t OK, tar -tzf OK, extracted log readable
BusyBox + unreadable file Still fails, permission error surfaced

Full suite: 1147 examples, 0 failures.

Docs

CHANGELOG.md entry, plus a new TROUBLESHOOTING.md section explaining that these
warnings are not failures and how to verify an archive by hand.

## Problem Odoo's volume backup failed most attempts: ``` Volume backup command failed (exit 1): tar: Removing leading `/' from member names tar: Removing leading `/' from hard link targets tar: /var/log/odoo/odoo-server.log: file changed as we read it ``` `tar` exits **1** for warning-level conditions ("some files differ") and reserves **2** for fatal errors. Odoo appends to its server log constantly, and that log lives inside a backed-up mount — so tar noticed the file growing under it and exited 1. `StreamingCommandExecutor` treated every non-zero exit as fatal, so the backup was discarded even though the archive was complete and restorable. Failures were intermittent because they depended on whether the app happened to write during tar's read window — hence "most" attempts, not all. ## Fix Tolerate warning-level tar exits — but **not on the exit code alone**. BusyBox tar exits 1 for genuine errors too: ``` $ docker run --rm busybox sh -c 'tar -czf - /nonexistent; echo exit=$?' tar: /nonexistent: No such file or directory tar: error exit delayed from previous errors exit=1 ``` So an exit of 1 is accepted only when **every** stderr line matches a known-benign warning (`file changed as we read it`, `File removed before we read it`, `socket ignored`, leading-slash notices). Anything unrecognised fails closed. - tar's exit semantics live in `VolumeBackupStrategy`, which already owns the tar command - `StreamingCommandExecutor` takes an injected `warning_filter:`; its default is unchanged, so database dumps still fail on any non-zero exit - Both volume paths fixed — in-container tar and the host-side `docker cp` fallback carried the same defect ## Verification Not just specs. Reproduced the real condition with a Debian container appending to a 30MB log on a mounted volume: | Scenario | Result | |---|---| | Pre-fix, 3 runs | **3/3 failed** with the exact reported error | | Post-fix, 5 runs | **5/5 succeeded** | | Archive integrity | `gzip -t` OK, `tar -tzf` OK, extracted log readable | | BusyBox + unreadable file | **Still fails**, permission error surfaced | Full suite: **1147 examples, 0 failures**. ## Docs `CHANGELOG.md` entry, plus a new `TROUBLESHOOTING.md` section explaining that these warnings are not failures and how to verify an archive by hand.
fix(backup): don't fail volume backups on warning-level tar exits
All checks were successful
Build, Push & Deploy / build-and-push (pull_request) Has been skipped
Build, Push & Deploy / deploy (Media) (pull_request) Has been skipped
Build, Push & Deploy / deploy (citadel) (pull_request) Has been skipped
Build, Push & Deploy / test (pull_request) Successful in 1m3s
8bf31645b7
tar exits 1 for warnings ("some files differ") and reserves 2 for fatal
errors. A container writing to its own data while it is archived -- an
application appending to a log file -- trips the warning, most reliably
with Odoo, whose server log lives inside a backed-up mount.

StreamingCommandExecutor treated every non-zero exit as fatal, so the
backup was discarded even though the archive was complete and
restorable. Failures were intermittent because they depended on whether
the app happened to write during tar's read window.

Tolerate warning-level tar exits, but not on the exit code alone:
BusyBox tar exits 1 for genuine errors too (verified: "can't open ...:
Permission denied" -> 1). An exit of 1 is accepted only when every
stderr line matches a known-benign warning, so permission errors and
missing paths still fail the backup.

tar's exit semantics live in VolumeBackupStrategy, which already owns
the tar command; the executor takes an injected warning_filter and its
default behaviour is unchanged, so database dumps still fail on any
non-zero exit. Both volume paths are covered -- in-container tar and
the host-side docker cp fallback carried the same defect.

Verified against live containers, not just specs: a Debian container
appending to a 30MB log reproduced the reported error 3/3 before the
fix and succeeded 5/5 after, with archives passing gzip -t and
extracting cleanly; a BusyBox container with an unreadable file still
fails and surfaces the permission error.

Co-Authored-By: Claude <noreply@anthropic.com>
james merged commit c52870ef29 into main 2026-07-30 15:42:41 +00:00
james deleted branch fix/volume-backup-tar-warning-exit 2026-07-30 15:42:49 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
james/baktainer!18
No description provided.