Borgmatic reports success but logs show stacktrace and no archive is created. #776

Closed
opened 2023-10-24 11:53:55 +00:00 by flightkick · 5 comments

What I'm trying to do and why

I'm trying to run another backup for which I expect an archive to be added.

Upon running the following command: borgmatic create --verbosity 1
The following output is produced:

backupserver: Creating archive
Traceback (most recent call last):
  File "/usr/bin/borg", line 33, in <module>
    sys.exit(load_entry_point('borgbackup==1.2.6', 'console_scripts', 'borg')())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5312, in main
    args = archiver.get_args(sys.argv, os.environ.get('SSH_ORIGINAL_COMMAND'))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5104, in get_args
    result = self.parse_args(argv[1:])
             ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5150, in parse_args
    args = parser.parse_args(args or ['-h'])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 1869, in parse_args
    args, argv = self.parse_known_args(args, namespace)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 1902, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2096, in _parse_known_args
    positionals_end_index = consume_positionals(start_index)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2073, in consume_positionals
    take_action(action, args)
  File "/usr/lib64/python3.11/argparse.py", line 1978, in take_action
    action(self, namespace, argument_values, option_string)
  File "/usr/lib64/python3.11/argparse.py", line 1241, in __call__
    subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 1902, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2114, in _parse_known_args
    start_index = consume_optional(start_index)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2054, in consume_optional
    take_action(action, args, option_string)
  File "/usr/lib64/python3.11/argparse.py", line 1978, in take_action
    action(self, namespace, argument_values, option_string)
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 59, in __call__
    self.parse(f, args)
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 64, in parse
    load_pattern_file(fobj, args.paths, args.patterns)
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 32, in load_pattern_file
    fallback = parse_patternfile_line(line, roots, ie_commands, fallback)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 17, in parse_patternfile_line
    ie_command = parse_inclexcl_command(line, fallback=fallback)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 384, in parse_inclexcl_command
    raise argparse.ArgumentTypeError("A pattern/command must start with anyone of: %s" %
argparse.ArgumentTypeError: A pattern/command must start with anyone of: -, !, +, R, r, P, p

summary:
/etc/borgmatic/config.yaml: Successfully ran configuration file

When inspecting the archives using borgmatic list, no additional archives seem to have been produced.
When using --verbosity 2 the stacktrace appears after this log line:

borg create --patterns-from /tmp/tmpjg_sxw0q --debug --show-rc ssh://borguser@borgrepository.address.example.com:1234//backup-path/example::{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f}

Steps to reproduce

Not entirely sure, here's part of my config from /etc/borgmatic/config.yaml:

source_directories:
    - /home/
    - /etc/
    - /root/
    - /var/lib/
    - /var/mail/
    - /var/www/
    - /var/games/
    - /var/backups/
    - /var/spool/cron/crontabs/
    - /var/local/
    - /var/opt/
    - /var/log/
    - /usr/local/bin/
    - /usr/local/sbin/
    - /usr/local/etc/
    - /usr/local/src/
    - /srv/
    - /opt/

When I run borgmatic with strace I see these being written to the tmp file:

openat(AT_FDCWD, "/tmp/tmpjg_sxw0q", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 3
ioctl(3, FIOCLEX)                       = 0
fstat(3, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(3, TCGETS, 0x7ffef92b69d0)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_CUR)                   = 0
write(3, "/.snapshots/\nR /etc/\nR /home/\nR /opt/\nR /root/\nR /srv/\nR /usr/local/bin/\nR /usr/local/etc/\nR /usr/local/sbin/\nR /usr/local/src/\nR /var/backups/\nR /var/games/\nR /var/lib/\nR /var/local/\nR /var/log/\nR /var/mail/\nR /var/opt/\nR /var/spool/cron/crontabs/\nR /var/www/", 260) = 260

Actual behavior

/etc/borgmatic/config.yaml: No commands to run for pre-everything hook
borg --version --debug --show-rc
backupserver: Running actions for repository
/etc/borgmatic/config.yaml: No commands to run for pre-actions hook
/etc/borgmatic/config.yaml: No commands to run for pre-backup hook
backupserver: Creating archive
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling mariadb_databases hook function remove_database_dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing MariaDB database dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling mysql_databases hook function remove_database_dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing MySQL database dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling mongodb_databases hook function remove_database_dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing MongoDB database dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling postgresql_databases hook function remove_database_dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing PostgreSQL database dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling sqlite_databases hook function remove_database_dumps
ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing SQLite database dumps
borg create --patterns-from /tmp/tmpjg_sxw0q --debug --show-rc ssh://borguser@borgrepository.address.example.com:1234//backup-path/example::{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f}
Traceback (most recent call last):
  File "/usr/bin/borg", line 33, in <module>
    sys.exit(load_entry_point('borgbackup==1.2.6', 'console_scripts', 'borg')())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5312, in main
    args = archiver.get_args(sys.argv, os.environ.get('SSH_ORIGINAL_COMMAND'))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5104, in get_args
    result = self.parse_args(argv[1:])
             ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5150, in parse_args
    args = parser.parse_args(args or ['-h'])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 1869, in parse_args
    args, argv = self.parse_known_args(args, namespace)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 1902, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2096, in _parse_known_args
    positionals_end_index = consume_positionals(start_index)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2073, in consume_positionals
    take_action(action, args)
  File "/usr/lib64/python3.11/argparse.py", line 1978, in take_action
    action(self, namespace, argument_values, option_string)
  File "/usr/lib64/python3.11/argparse.py", line 1241, in __call__
    subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 1902, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2114, in _parse_known_args
    start_index = consume_optional(start_index)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/argparse.py", line 2054, in consume_optional
    take_action(action, args, option_string)
  File "/usr/lib64/python3.11/argparse.py", line 1978, in take_action
    action(self, namespace, argument_values, option_string)
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 59, in __call__
    self.parse(f, args)
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 64, in parse
    load_pattern_file(fobj, args.paths, args.patterns)
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 32, in load_pattern_file
    fallback = parse_patternfile_line(line, roots, ie_commands, fallback)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 17, in parse_patternfile_line
    ie_command = parse_inclexcl_command(line, fallback=fallback)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 384, in parse_inclexcl_command
    raise argparse.ArgumentTypeError("A pattern/command must start with anyone of: %s" %
argparse.ArgumentTypeError: A pattern/command must start with anyone of: -, !, +, R, r, P, p
/etc/borgmatic/config.yaml: Calling mariadb_databases hook function remove_database_dumps
/etc/borgmatic/config.yaml: Removing MariaDB database dumps
/etc/borgmatic/config.yaml: Calling mysql_databases hook function remove_database_dumps
/etc/borgmatic/config.yaml: Removing MySQL database dumps
/etc/borgmatic/config.yaml: Calling mongodb_databases hook function remove_database_dumps
/etc/borgmatic/config.yaml: Removing MongoDB database dumps
/etc/borgmatic/config.yaml: Calling postgresql_databases hook function remove_database_dumps
/etc/borgmatic/config.yaml: Removing PostgreSQL database dumps
/etc/borgmatic/config.yaml: Calling sqlite_databases hook function remove_database_dumps
/etc/borgmatic/config.yaml: Removing SQLite database dumps
/etc/borgmatic/config.yaml: No commands to run for post-backup hook
/etc/borgmatic/config.yaml: No commands to run for post-actions hook
/etc/borgmatic/config.yaml: No commands to run for post-everything hook

summary:
/etc/borgmatic/config.yaml: Loading configuration file
/etc/borgmatic/config.yaml: Successfully ran configuration file

Expected behavior

  • Best case scenario I would expect the backup to succeed and another archive to be created.
  • Worst case scenario I would expect an informative error message that guides me to fix the issue if it is caused on my end.
  • At least I would expect borgmatic to not report success in case of a failure.

Other notes / implementation ideas

No response

borgmatic version

1.8.2

borgmatic installation method

OpenSUSE package (zypper)

Borg version

1.2.6

Python version

3.11.5

Database version (if applicable)

-

Operating system and version

NAME="openSUSE Tumbleweed" # VERSION="20231022"

### What I'm trying to do and why I'm trying to run another backup for which I expect an archive to be added. Upon running the following command: `borgmatic create --verbosity 1` The following output is produced: ``` backupserver: Creating archive Traceback (most recent call last): File "/usr/bin/borg", line 33, in <module> sys.exit(load_entry_point('borgbackup==1.2.6', 'console_scripts', 'borg')()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5312, in main args = archiver.get_args(sys.argv, os.environ.get('SSH_ORIGINAL_COMMAND')) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5104, in get_args result = self.parse_args(argv[1:]) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5150, in parse_args args = parser.parse_args(args or ['-h']) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 1869, in parse_args args, argv = self.parse_known_args(args, namespace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 1902, in parse_known_args namespace, args = self._parse_known_args(args, namespace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 2096, in _parse_known_args positionals_end_index = consume_positionals(start_index) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 2073, in consume_positionals take_action(action, args) File "/usr/lib64/python3.11/argparse.py", line 1978, in take_action action(self, namespace, argument_values, option_string) File "/usr/lib64/python3.11/argparse.py", line 1241, in __call__ subnamespace, arg_strings = parser.parse_known_args(arg_strings, None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 1902, in parse_known_args namespace, args = self._parse_known_args(args, namespace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 2114, in _parse_known_args start_index = consume_optional(start_index) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 2054, in consume_optional take_action(action, args, option_string) File "/usr/lib64/python3.11/argparse.py", line 1978, in take_action action(self, namespace, argument_values, option_string) File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 59, in __call__ self.parse(f, args) File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 64, in parse load_pattern_file(fobj, args.paths, args.patterns) File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 32, in load_pattern_file fallback = parse_patternfile_line(line, roots, ie_commands, fallback) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 17, in parse_patternfile_line ie_command = parse_inclexcl_command(line, fallback=fallback) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 384, in parse_inclexcl_command raise argparse.ArgumentTypeError("A pattern/command must start with anyone of: %s" % argparse.ArgumentTypeError: A pattern/command must start with anyone of: -, !, +, R, r, P, p summary: /etc/borgmatic/config.yaml: Successfully ran configuration file ``` When inspecting the archives using `borgmatic list`, no additional archives seem to have been produced. When using `--verbosity 2` the stacktrace appears after this log line: ``` borg create --patterns-from /tmp/tmpjg_sxw0q --debug --show-rc ssh://borguser@borgrepository.address.example.com:1234//backup-path/example::{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f} ``` ### Steps to reproduce Not entirely sure, here's part of my config from `/etc/borgmatic/config.yaml`: ```yaml source_directories: - /home/ - /etc/ - /root/ - /var/lib/ - /var/mail/ - /var/www/ - /var/games/ - /var/backups/ - /var/spool/cron/crontabs/ - /var/local/ - /var/opt/ - /var/log/ - /usr/local/bin/ - /usr/local/sbin/ - /usr/local/etc/ - /usr/local/src/ - /srv/ - /opt/ ``` When I run borgmatic with strace I see these being written to the tmp file: ``` openat(AT_FDCWD, "/tmp/tmpjg_sxw0q", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 3 ioctl(3, FIOCLEX) = 0 fstat(3, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 ioctl(3, TCGETS, 0x7ffef92b69d0) = -1 ENOTTY (Inappropriate ioctl for device) lseek(3, 0, SEEK_CUR) = 0 lseek(3, 0, SEEK_CUR) = 0 write(3, "/.snapshots/\nR /etc/\nR /home/\nR /opt/\nR /root/\nR /srv/\nR /usr/local/bin/\nR /usr/local/etc/\nR /usr/local/sbin/\nR /usr/local/src/\nR /var/backups/\nR /var/games/\nR /var/lib/\nR /var/local/\nR /var/log/\nR /var/mail/\nR /var/opt/\nR /var/spool/cron/crontabs/\nR /var/www/", 260) = 260 ``` ### Actual behavior ``` /etc/borgmatic/config.yaml: No commands to run for pre-everything hook borg --version --debug --show-rc backupserver: Running actions for repository /etc/borgmatic/config.yaml: No commands to run for pre-actions hook /etc/borgmatic/config.yaml: No commands to run for pre-backup hook backupserver: Creating archive ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling mariadb_databases hook function remove_database_dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing MariaDB database dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling mysql_databases hook function remove_database_dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing MySQL database dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling mongodb_databases hook function remove_database_dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing MongoDB database dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling postgresql_databases hook function remove_database_dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing PostgreSQL database dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Calling sqlite_databases hook function remove_database_dumps ssh://borguser@borgrepository.address.example.com:1234//backup-path/example: Removing SQLite database dumps borg create --patterns-from /tmp/tmpjg_sxw0q --debug --show-rc ssh://borguser@borgrepository.address.example.com:1234//backup-path/example::{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f} Traceback (most recent call last): File "/usr/bin/borg", line 33, in <module> sys.exit(load_entry_point('borgbackup==1.2.6', 'console_scripts', 'borg')()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5312, in main args = archiver.get_args(sys.argv, os.environ.get('SSH_ORIGINAL_COMMAND')) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5104, in get_args result = self.parse_args(argv[1:]) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/archiver.py", line 5150, in parse_args args = parser.parse_args(args or ['-h']) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 1869, in parse_args args, argv = self.parse_known_args(args, namespace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 1902, in parse_known_args namespace, args = self._parse_known_args(args, namespace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 2096, in _parse_known_args positionals_end_index = consume_positionals(start_index) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 2073, in consume_positionals take_action(action, args) File "/usr/lib64/python3.11/argparse.py", line 1978, in take_action action(self, namespace, argument_values, option_string) File "/usr/lib64/python3.11/argparse.py", line 1241, in __call__ subnamespace, arg_strings = parser.parse_known_args(arg_strings, None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 1902, in parse_known_args namespace, args = self._parse_known_args(args, namespace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 2114, in _parse_known_args start_index = consume_optional(start_index) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/argparse.py", line 2054, in consume_optional take_action(action, args, option_string) File "/usr/lib64/python3.11/argparse.py", line 1978, in take_action action(self, namespace, argument_values, option_string) File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 59, in __call__ self.parse(f, args) File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 64, in parse load_pattern_file(fobj, args.paths, args.patterns) File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 32, in load_pattern_file fallback = parse_patternfile_line(line, roots, ie_commands, fallback) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 17, in parse_patternfile_line ie_command = parse_inclexcl_command(line, fallback=fallback) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/site-packages/borg/patterns.py", line 384, in parse_inclexcl_command raise argparse.ArgumentTypeError("A pattern/command must start with anyone of: %s" % argparse.ArgumentTypeError: A pattern/command must start with anyone of: -, !, +, R, r, P, p /etc/borgmatic/config.yaml: Calling mariadb_databases hook function remove_database_dumps /etc/borgmatic/config.yaml: Removing MariaDB database dumps /etc/borgmatic/config.yaml: Calling mysql_databases hook function remove_database_dumps /etc/borgmatic/config.yaml: Removing MySQL database dumps /etc/borgmatic/config.yaml: Calling mongodb_databases hook function remove_database_dumps /etc/borgmatic/config.yaml: Removing MongoDB database dumps /etc/borgmatic/config.yaml: Calling postgresql_databases hook function remove_database_dumps /etc/borgmatic/config.yaml: Removing PostgreSQL database dumps /etc/borgmatic/config.yaml: Calling sqlite_databases hook function remove_database_dumps /etc/borgmatic/config.yaml: Removing SQLite database dumps /etc/borgmatic/config.yaml: No commands to run for post-backup hook /etc/borgmatic/config.yaml: No commands to run for post-actions hook /etc/borgmatic/config.yaml: No commands to run for post-everything hook summary: /etc/borgmatic/config.yaml: Loading configuration file /etc/borgmatic/config.yaml: Successfully ran configuration file ``` ### Expected behavior - Best case scenario I would expect the backup to succeed and another archive to be created. - Worst case scenario I would expect an informative error message that guides me to fix the issue if it is caused on my end. - At least I would expect borgmatic to not report success in case of a failure. ### Other notes / implementation ideas _No response_ ### borgmatic version 1.8.2 ### borgmatic installation method OpenSUSE package (zypper) ### Borg version 1.2.6 ### Python version 3.11.5 ### Database version (if applicable) \- ### Operating system and version NAME="openSUSE Tumbleweed" # VERSION="20231022"
Owner

Thanks for filing this! It looks like the traceback you're seeing is coming from Borg rather than borgmatic itself.

At least I would expect borgmatic to not report success in case of a failure.

Yes, this sounds like a potential bug. borgmatic should be handling the Borg error more gracefully.

Best case scenario I would expect the backup to succeed and another archive to be created.

borgmatic relies on Borg to create the archive. So if Borg errors, it won't be created.

Worst case scenario I would expect an informative error message that guides me to fix the issue if it is caused on my end.

Ideally, yes. However there are cases where the best borgmatic can do is provide the exact error that Borg produces, as there may not be any additional information about the issue.

In any case, to determine the cause of your patterns issue and help reproduce the potential "success" bug, can I get a look at your entire configuration file? Feel free to redact anything you don't want to share.

Thank you!

Thanks for filing this! It looks like the traceback you're seeing is coming from Borg rather than borgmatic itself. > At least I would expect borgmatic to not report success in case of a failure. Yes, this sounds like a potential bug. borgmatic should be handling the Borg error more gracefully. > Best case scenario I would expect the backup to succeed and another archive to be created. borgmatic relies on Borg to create the archive. So if Borg errors, it won't be created. > Worst case scenario I would expect an informative error message that guides me to fix the issue if it is caused on my end. Ideally, yes. However there are cases where the best borgmatic can do is provide the exact error that Borg produces, as there may not be any additional information about the issue. In any case, to determine the cause of your patterns issue and help reproduce the potential "success" bug, can I get a look at your entire configuration file? Feel free to redact anything you don't want to share. Thank you!
Author

@witten Thank you for the help, appreciated!

Turns out that if you spend time on writing a full bug report, you might as well not skip that tiny bit of effort to gather the full config. After copying the config and removing the comments through some regex, I discovered that I had a strange config for pattern exclusions. After correcting this, the issue was gone.

Culprit:

patterns:
    - /.snapshots/

Fixed config:

patterns:
    - R /
    - '- /.snapshots/'

At least this report can still be used to handle borg errors more gracefully.

borgmatic relies on Borg to create the archive. So if Borg errors, it won't be created.

I guess I didn't properly formulate my expectation for this case, it cannot be seen in isolation from the others (as in; either I expect a failure and nothing is created or I expect success and a created archive). I do understand the dependency.

Ideally, yes. However there are cases where the best borgmatic can do is provide the exact error that Borg produces, as there may not be any additional information about the issue.

Even pointing out that borg threw an exception and therefore borgmatic couldn't produce a new artifact would be productive guidance towards detecting and solving the issue. As borgmatic create without any arguments doesn't produce any output and still exited with code 0, it took adding the --verbose 2 flag to discover that something was failing underneath. After discovering the stacktrace and exception though, I'm the one to blame for misinterpreting the 'pattern' error, thought it was referring to the paths declared under source_directories somehow.

Strangely, running borgmatic config validate didn't report any issues with that broken config.

@witten Thank you for the help, appreciated! Turns out that if you spend time on writing a full bug report, you might as well not skip that tiny bit of effort to gather the full config. After copying the config and removing the comments through some regex, I discovered that I had a strange config for pattern exclusions. After correcting this, the issue was gone. Culprit: ```yaml patterns: - /.snapshots/ ``` Fixed config: ```yaml patterns: - R / - '- /.snapshots/' ``` ----- At least this report can still be used to handle borg errors more gracefully. > borgmatic relies on Borg to create the archive. So if Borg errors, it won't be created. I guess I didn't properly formulate my expectation for this case, it cannot be seen in isolation from the others (as in; either I expect a failure and nothing is created or I expect success and a created archive). I do understand the dependency. > Ideally, yes. However there are cases where the best borgmatic can do is provide the exact error that Borg produces, as there may not be any additional information about the issue. Even pointing out that borg threw an exception and therefore borgmatic couldn't produce a new artifact would be productive guidance towards detecting and solving the issue. As `borgmatic create` without any arguments doesn't produce any output and still exited with code 0, it took adding the `--verbose 2` flag to discover that something was failing underneath. After discovering the stacktrace and exception though, I'm the one to blame for misinterpreting the 'pattern' error, thought it was referring to the paths declared under `source_directories` somehow. Strangely, running `borgmatic config validate` didn't report any issues with that broken config.
Owner

At least this report can still be used to handle borg errors more gracefully.

Yup, I'll see if I can reproduce the problem here and hopefully fix it.

After discovering the stacktrace and exception though, I'm the one to blame for misinterpreting the 'pattern' error, thought it was referring to the paths declared under source_directories somehow.

I think that's because if you've got any patterns, borgmatic adds your source directories to them as root directories before passing the patterns to Borg. (Due to #574 and #590.) That's a work-around for a now-fixed Borg bug: https://github.com/borgbackup/borg/issues/6994

Strangely, running borgmatic config validate didn't report any issues with that broken config.

borgmatic's config validation just ensures that the configuration adheres to the schema. It doesn't actually parse the Borg patterns to make sure they're well-formed. Maybe that could be an enhancement though.

> At least this report can still be used to handle borg errors more gracefully. Yup, I'll see if I can reproduce the problem here and hopefully fix it. > After discovering the stacktrace and exception though, I'm the one to blame for misinterpreting the 'pattern' error, thought it was referring to the paths declared under source_directories somehow. I think that's because if you've got any patterns, borgmatic adds your source directories to them as root directories before passing the patterns to Borg. (Due to #574 and #590.) That's a work-around for a now-fixed Borg bug: https://github.com/borgbackup/borg/issues/6994 > Strangely, running borgmatic config validate didn't report any issues with that broken config. borgmatic's config validation just ensures that the configuration adheres to the schema. It doesn't actually parse the Borg patterns to make sure they're well-formed. Maybe that could be an enhancement though.
Owner

An update: I managed to get a repro on this issue. Just had to add an invalid pattern line like you described.

Edit: Borg is returning an exit code of 1, which indicates a warning rather than an error! That's why borgmatic is treating it as a success.

Edit 2: I filed a Borg ticket on this.

An update: I managed to get a repro on this issue. Just had to add an invalid pattern line like you described. Edit: Borg is returning an exit code of 1, which indicates a warning rather than an error! That's why borgmatic is treating it as a success. Edit 2: I filed a [Borg ticket](https://github.com/borgbackup/borg/issues/7885) on this.
witten added the
bug
label 2023-10-25 06:20:14 +00:00
Owner

The underlying issue resulting in "success" has been fixed in Borg (not borgmatic), and will be part of the next Borg release (1.2.7). So I'm not going to try to work around the issue in borgmatic. Thanks again for filing this issue—it's the reason it got fixed in Borg!

The underlying issue resulting in "success" has been [fixed in Borg](https://github.com/borgbackup/borg/issues/7885) (not borgmatic), and will be part of the next Borg release (1.2.7). So I'm not going to try to work around the issue in borgmatic. Thanks again for filing this issue—it's the reason it got fixed in Borg!
witten removed the
bug
label 2023-10-25 15:24:43 +00:00
Sign in to join this conversation.
No Milestone
No Assignees
2 Participants
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: borgmatic-collective/borgmatic#776
No description provided.