unexpected error when backing up databases without source_directories #655
Labels
No Label
bug
data loss
design finalized
good first issue
new feature area
question / support
security
waiting for response
No Milestone
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: borgmatic-collective/borgmatic#655
Loadingโฆ
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What I'm trying to do and why
I tried to dump a database in borgmatic without adding any source directories (didn't want to backup files).
Steps to reproduce (if a bug)
do same as above.
Actual behavior (if a bug)
Borgmatic reports a weird error.
Expected behavior (if a bug)
Borgmatic should not raise an error if
source_directories_must_exist
is False, and raise one (a better one) if it is True, this is already handled.Other notes / implementation ideas
Check the discussion here - https://github.com/borgmatic-collective/borgmatic/pull/53
Environment
borgmatic version: [version here]
Use
sudo borgmatic --version
orsudo pip show borgmatic | grep ^Version
borgmatic installation method: [e.g., Debian package, Docker container, etc.]
Borg version: [version here]
Use
sudo borg --version
Python version: [version here]
Use
python3 --version
Database version (if applicable): [version here]
Use
psql --version
ormysql --version
on client and server.operating system and version: [OS here]
Borgmatic raises unexpected error when backing up databases without source_directoriesto unexpected error when backing up databases without source_directoriesA copy/paste of a relevant comment on the linked GitHub PR:
So I think you found a legitimate bug in the current code! It looks like when database hooks are enabled and a non-existent directory is given in
source_directories
, then borgmatic gives the weird error message above (in your first screenshot) and exits. That's not intentional; non-existent source directories aren't supposed to cause errors (without your new option being set). When database hooks are not enabled and a non-existent directory is given insource_directories
, Borg issues a warning but then continues on without any error, like this:Anyway, I think the bug you've uncovered occurs in
collect_special_file_paths()
inborgmatic/borg/create.py
, which is triggered when a database hook is configured (orread_special
is set totrue
). Specifically, the call toexecute_command_and_capture_output()
there blows up when one of the directories doesn't exist. At least, I think that's what's going on. If you want to try to fix the bug as part of this ticket it, you are welcome to do so. Otherwise, feel free to file it or just let me know and I'd be happy to have a look.@diivi wrote:
It's because database hooks being configured implicitly enables the
read_special
option, and thecollect_special_file_paths()
code path is only executed whenread_special
is true.I think the difference here is how it's executed. Specifically, check out
exit_code_indicates_error()
inborgmatic/execute.py
. What that function does is look at the Borg exit code and decide whether to call it an error or not. So exit status < 2 (e.g., 1 in this case, which is what Borg returns when a source file doesn't exist) is not treated as an error.And here's the tricky part:
exit_code_indicates_error()
isn't always used. Lets say you callborgmatic create
without any databases configured. That callsexecute_command()
which callslog_outputs()
which callsexit_code_indicates_error()
to determine what to do with Borg's exit code.In contrast though, when you call
borgmatic create
with databases configured,read_special
kicks on andcollect_special_file_paths()
is called prior toborg create
. Andcollect_special_file_paths()
callsexecute_command_and_capture_output()
, which calls Python'ssubprocess.check_output()
, which raises regardless of the exit code as long as it's non-zero. Meaning the usual Borg exit code of 1 for a non-existent file is treated as an error instead of a warning. And boom, ugly error.So what's the fix? It might be not using
check_output()
withinexecute_command_and_capture_output()
and callingexit_code_indicates_error()
there to take appropriate action on the result. (Or, continuing to usecheck_output()
but catching the exception and dealing with it as needed based on theexit_code_indicates_error()
result.)The one caveat is that any fix should ideally not break other uses cases. For example, there might be other callers of
execute_command_and_capture_output()
that implicitly expect an exit code of 1 to be treated as an error.Also, don't feel obligated to dive into fixing this just because you found the problem. People file borgmatic bugs and then don't fix them themselves all the time. ๐
Fixed by @diivi here: https://github.com/borgmatic-collective/borgmatic/pull/56!
Released in borgmatic 1.7.10!