From 06c86d6c58f7aa52b0310f5dccb6848493878eff Mon Sep 17 00:00:00 2001 From: sebastienclaude <44704752+sebastienclaude@users.noreply.github.com> Date: Mon, 22 Jun 2026 12:03:05 +0200 Subject: [PATCH] [FIX] auto_backup: open cached dump in binary mode When several `db.backup` records use `method=local`, only the first one performs the actual dump; the subsequent local records copy the file written by the first via `shutil.copyfileobj(cached, destiny)`. The source file `cached` was opened with `open(backup)`, which defaults to text mode. Python then tries to UTF-8 decode the binary dump (ZIP or SQL with non-UTF-8 bytes) and aborts with:: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 12: invalid continuation byte The destination is already opened with `"wb"`, so the fix is to open the cached source with `"rb"` too. Reproduced and fixed on a production instance with two `db.backup` records both in `method=local` (local disk + CIFS mount). After the patch the second copy is byte-identical to the first dump. The same defect is present on branches 16.0 and 17.0 of this module. Signed-off-by: sebastienclaude <44704752+sebastienclaude@users.noreply.github.com> --- auto_backup/__manifest__.py | 2 +- auto_backup/models/db_backup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/auto_backup/__manifest__.py b/auto_backup/__manifest__.py index 3c7ab7471ac..36e8c5ea86a 100644 --- a/auto_backup/__manifest__.py +++ b/auto_backup/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Database Auto-Backup", "summary": "Backups database", - "version": "18.0.1.0.1", + "version": "18.0.1.0.2", "author": "Yenthe Van Ginneken, " "Agile Business Group, " "Grupo ESOC Ingenieria de Servicios, " diff --git a/auto_backup/models/db_backup.py b/auto_backup/models/db_backup.py index 042038e6183..d38285e4145 100644 --- a/auto_backup/models/db_backup.py +++ b/auto_backup/models/db_backup.py @@ -154,7 +154,7 @@ def action_backup(self): with open(os.path.join(rec.folder, filename), "wb") as destiny: # Copy the cached backup if backup: - with open(backup) as cached: + with open(backup, "rb") as cached: shutil.copyfileobj(cached, destiny) # Generate new backup else: