Skip to content

create: implement retries for individual fs files - #7351

Merged
ThomasWaldmann merged 1 commit into
borgbackup:masterfrom
ThomasWaldmann:retry-failed-files
Feb 23, 2023
Merged

create: implement retries for individual fs files#7351
ThomasWaldmann merged 1 commit into
borgbackup:masterfrom
ThomasWaldmann:retry-failed-files

Conversation

@ThomasWaldmann

@ThomasWaldmann ThomasWaldmann commented Feb 13, 2023

Copy link
Copy Markdown
Member

Errors handled for backup src files:

  • BackupOSError (converted from OSError), e.g. I/O Error
  • BackupError (stats race, file changed while we backed it up)

Error Handling:

  • retry the same file after some sleep time
  • sleep time starts from 1ms, increases exponentially up to 10s
  • 10 tries

If retrying does not help:

  • BackupOSError: skip the file, log it with "E" status
  • BackupError: last try will back it up, log it with "C" status

Works for:

  • borg create's normal (builtin) fs recursion
  • borg create --paths-from-command
  • borg create --paths-from-stdin

Notes:

  • update stats.files_stats late (so we don't get wrong
    stats in case of e.g. IOErrors while reading the file).
  • _process_any: no changes to the big block, just indented
    for adding the retry loop and the try/except.
  • test_create_erroneous_file succeeds because we retry the file.

@codecov-commenter

codecov-commenter commented Feb 13, 2023

Copy link
Copy Markdown

Codecov Report

Merging #7351 (dc491db) into master (3f2aac8) will decrease coverage by 0.05%.
The diff coverage is 54.54%.

❗ Current head dc491db differs from pull request most recent head 7e6afc9. Consider uploading reports for the commit 7e6afc9 to get more accurate results

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

@@            Coverage Diff             @@
##           master    #7351      +/-   ##
==========================================
- Coverage   83.98%   83.93%   -0.05%     
==========================================
  Files          67       67              
  Lines       11692    11707      +15     
  Branches     2126     2131       +5     
==========================================
+ Hits         9819     9826       +7     
- Misses       1312     1317       +5     
- Partials      561      564       +3     
Impacted Files Coverage Δ
src/borg/archive.py 84.62% <44.44%> (-0.10%) ⬇️
src/borg/archiver/create_cmd.py 78.35% <56.52%> (-1.08%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@ThomasWaldmann ThomasWaldmann changed the title create: implement retries for fs files create: implement retries for individual fs files Feb 14, 2023
Comment thread src/borg/archiver/create_cmd.py Outdated
Comment thread src/borg/archiver/create_cmd.py Outdated
@ThomasWaldmann ThomasWaldmann added this to the 2.0.0b5 milestone Feb 19, 2023
Errors handled for backup src files:
- BackupOSError (converted from OSError), e.g. I/O Error
- BackupError (stats race, file changed while we backed it up)

Error Handling:
- retry the same file after some sleep time
- sleep time starts from 1ms, increases exponentially up to 10s
- 10 tries

If retrying does not help:
- BackupOSError: skip the file, log it with "E" status
- BackupError: last try will back it up, log it with "C" status

Works for:
- borg create's normal (builtin) fs recursion
- borg create --paths-from-command
- borg create --paths-from-stdin

Notes:
- update stats.files_stats late (so we don't get wrong
  stats in case of e.g. IOErrors while reading the file).
- _process_any: no changes to the big block, just indented
  for adding the retry loop and the try/except.
- test_create_erroneous_file succeeds because we retry the file.
@ThomasWaldmann
ThomasWaldmann merged commit b208785 into borgbackup:master Feb 23, 2023
@ThomasWaldmann
ThomasWaldmann deleted the retry-failed-files branch February 23, 2023 00:46
@drzraf

drzraf commented Jun 23, 2026

Copy link
Copy Markdown

any chance this one could be backported to 1.4.x ?

@ThomasWaldmann

Copy link
Copy Markdown
Member Author

@drzraf Originally, I did not intend to backport this.

Can you tell me your use case, so I maybe can re-evaluate?

@sophie-h

Copy link
Copy Markdown
Contributor

My observation is that file changes happen very frequently on desktop backups. SQLite dbs for messengers, browser databases for bookmarks etc

@drzraf

drzraf commented Jun 24, 2026

Copy link
Copy Markdown

My observation is that file changes happen very frequently on desktop backups. SQLite dbs for messengers, browser databases for bookmarks etc

Exactly this.
It creates a lot of noise / false alerts, especially when backup's cron output is consider a significant warning/failure worth to be emailed.

(I've been a very satisfied user of Borg for years, but this particular output/behavioral tweak is what I've awaiting the most :))

@ThomasWaldmann

Copy link
Copy Markdown
Member Author

@drzraf @sophie-h see #9805.

ThomasWaldmann added a commit to ThomasWaldmann/borg that referenced this pull request Jul 5, 2026
…ckup#7351)

Backport of borgbackup#7351 to 1.4-maint. Retry reading a backup source file when
it raises a BackupError / BackupOSError (e.g. transient I/O error, or the
file changed while we read it):
- retry the same file after some sleep time (1ms, growing exponentially up to 10s, 10 tries)
- BackupOSError: if retries do not help, skip the file, log it with "E" status
- BackupError (changed while reading): last try backs it up, logged with "C" status

Works for borg create's builtin fs recursion, --paths-from-command and --paths-from-stdin.

1.4-specific: do NOT retry a file once checkpoint part files (.borg_part_N)
have been written for it. Re-reading it from the start would create duplicate /
inconsistent part files (concatenating all part files would then no longer yield
the complete file). ChunksProcessor.last_part_number tracks this; such a file is
kept as-is ("C") or skipped ("E") instead of being retried.

Permission errors (EPERM/EACCES) are not retried (they won't get better),
so we don't waste ~15s of backoff on every unreadable file.

Adds a ChunkerFailing test chunker (chunker-params=fail,block_size,map) to drive
the error handling, and tests:
- test_create_erroneous_file: file is read on a later retry
- test_create_no_permission_file: permission error is not retried, file skipped
- test_create_erroneous_file_with_part_files: file with part files is not retried

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ThomasWaldmann added a commit to ThomasWaldmann/borg that referenced this pull request Jul 7, 2026
…ckup#7351)

Backport of borgbackup#7351 to 1.4-maint. Retry reading a backup source file when
it raises a BackupError / BackupOSError (e.g. transient I/O error, or the
file changed while we read it):
- retry the same file after some sleep time (1ms, growing exponentially up to 10s, 10 tries)
- BackupOSError: if retries do not help, skip the file, log it with "E" status
- BackupError (changed while reading): last try backs it up, logged with "C" status

Works for borg create's builtin fs recursion, --paths-from-command and --paths-from-stdin.

1.4-specific: do NOT retry a file once checkpoint part files (.borg_part_N)
have been written for it. Re-reading it from the start would create duplicate /
inconsistent part files (concatenating all part files would then no longer yield
the complete file). ChunksProcessor.last_part_number tracks this; such a file is
kept as-is ("C") or skipped ("E") instead of being retried.

Permission errors (EPERM/EACCES) are not retried (they won't get better),
so we don't waste ~15s of backoff on every unreadable file.

Adds a ChunkerFailing test chunker (chunker-params=fail,block_size,map) to drive
the error handling, and tests:
- test_create_erroneous_file: file is read on a later retry
- test_create_no_permission_file: permission error is not retried, file skipped
- test_create_erroneous_file_with_part_files: file with part files is not retried

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants