Skip to content

fix: distinguish LockFailed causes instead of always blaming permissions - #2545

Open
kreativmonkey wants to merge 1 commit into
borgbase:masterfrom
kreativmonkey:fix/lockfailed-distinguish-causes
Open

fix: distinguish LockFailed causes instead of always blaming permissions#2545
kreativmonkey wants to merge 1 commit into
borgbase:masterfrom
kreativmonkey:fix/lockfailed-distinguish-causes

Conversation

@kreativmonkey

Copy link
Copy Markdown

Description

Borg raises LockFailed for any failure to create the lock file, but react_to_log() reported every one of them as "No Repository Permissions". The dialog also never showed what Borg actually said, because borg_job.py dropped the message before it reached the signal context.

Two changes:

  • src/vorta/borg/borg_job.py — put parsed['message'] into the context dict that goes out with backup_log_event. The only other consumer of that context is MainWindow.set_log(), which ignores it, so nothing else is affected.
  • src/vorta/application.py — in the LockFailed branch, decide by the errno contained in Borg's message: 28 / 122 / 69 → "Repository Storage Full", 1 / 13 → the existing "No Repository Permissions" wording, anything else → a neutral "Repository Lock Failed". Borg's original message is attached as detailed text in all three cases, so a cause the branching does not know about is still visible to the user.

Two details worth flagging:

  • The match is on the number in [Errno N], not on the text after it. That text comes from strerror and is localized — under a German locale the quota error reads "Der Speicherplatz auf dem Datenträger wurde überschritten".
  • The errno values are hardcoded rather than taken from Python's errno module, because for a remote repository the error happens on the server. A macOS client backing up to a Linux server gets 122, which is not what errno.EDQUOT is on macOS. There is a comment in the code saying so.

The storage-full text also mentions that pruning won't work either, since that is the part that costs people time: borg prune needs the same lock it cannot write, so the repository has to be freed up from outside.

The three strings I touched were changed from self.tr(f"…{repo_url}…") to self.tr("…{}…").format(repo_url). The f-string is interpolated before tr() sees it, so the lookup key never matches the catalog and the line cannot be translated. The same pattern exists in a few other places (LockTimeout right above, filedialog.py, repo_tab.py) — I left those alone to keep this PR to one topic. Happy to open a separate issue for them if you want it fixed.

No .ts/.qm files touched.

Related Issue

#2544

Motivation and Context

My backups to a Hetzner Storage Box started failing and Vorta told me I had no permission to access the repository. I spent a while checking the SSH key and the permissions on the server before running Borg by hand, which said:

Failed to create/acquire the lock /home/repo/lock.exclusive
([Errno 122] Disk quota exceeded: '/home/repo/lock.exclusive.xn0egqgt.tmp').

[Errno 122] is EDQUOT — the box was 100 % full. With this change the dialog names that, and shows Borg's message either way.

How Has This Been Tested?

Arch Linux, Python 3.14, PyQt6, Borg 1.4.5.

  • tests/unit/test_lock.py::test_create_perm_error is unchanged and still passes — its fixture carries [Errno 13], so it is the regression guard for the permissions branch.
  • Added test_create_quota_error with a new create_quota fixture pair carrying the real [Errno 122] message; asserts the new wording and that the Borg message ends up in the detailed text.
  • Added test_create_lock_failed_generic with a create_lockfail fixture using [Errno 30] (read-only filesystem) to cover the fallback branch.
  • QT_QPA_PLATFORM=offscreen uv run pytest tests/unit → 257 passed, 6 skipped.
  • make lint → all pre-commit hooks pass.

Note for anyone reproducing: running tests/unit/test_lock.py on its own fails on test_create_perm_error with a waitUntil timeout. That is pre-existing on master, unrelated to this change — the file depends on state another test module sets up first. It passes in the full suite.

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have read the CONTRIBUTING guide.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

I provide my contribution under the terms of the license of this repository and I affirm the Developer Certificate of Origin.

Borg raises LockFailed for any failure to create the lock file, but Vorta
reported every one of them as "No Repository Permissions". A repository
whose backing storage is full ([Errno 122] on Linux, [Errno 28] anywhere)
therefore sent users looking at SSH keys and permissions.

Pass Borg's message along in the log signal context and branch on the errno
it contains. Borg's original message is now always shown as detailed text,
so a cause the branching does not know about is still visible.

Refs borgbase#2544
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.

1 participant