Skip to content

LockFailed is always reported as a permissions problem, even when the repository storage is full #2544

Description

@kreativmonkey

Description

My daily backups to a Hetzner Storage Box started failing yesterday. Vorta showed me this dialog:

No Repository Permissions
You do not have permission to access the repository at ssh://user@example-storage.invalid:23/./repo. Gain access and try again.

So I spent a while on the wrong problem — checked the SSH key, re-added it to the box, checked the repo path and permissions on the server. All fine. The key authenticates, and read-only Borg commands with --bypass-lock worked the whole time.

The actual cause only showed up when I ran Borg by hand:

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 Storage Box was 100 % full:

Filesystem      1K-blocks       Used Available Use% Mounted on
u294544-sub1   1071327104 1071327104         0 100% /home

Borg raises LockFailed for any failure to create the lock file, not just permission errors, but Vorta reports every LockFailed as a permissions problem.

What made it worse: a full repo is a dead end that the UI gives no way out of. borg prune — the one thing that would free space — needs the same lock it can't write, so it fails too. Even prune --dry-run fails. Without seeing the real error there's no hint that the fix has to happen outside the repository.

Where it comes from

src/vorta/borg/borg_job.py (master, L284-289) builds the signal context without Borg's message:

context = {
    'msgid': parsed.get('msgid'),
    'repo_url': self.params['repo_url'],
    'profile_name': self.params.get('profile_name'),
    'cmd': self.params['cmd'][1],
}

The message only goes into the formatted log string, not into the dict. So react_to_log() in src/vorta/application.py (master, L259-269) has nothing to go on and hardcodes the permission wording for every LockFailed:

elif msgid == 'LockFailed':
    repo_url = context.get('repo_url')
    msg = QMessageBox()
    msg.setText(
        self.tr(
            f"You do not have permission to access the repository at {repo_url}. Gain access and try again."
        )
    )  # noqa: E501
    msg.setWindowTitle(self.tr("No Repository Permissions"))

Both are unchanged on current master (b2272ae) and identical to what ships in 0.11.5.

Suggested fix

Pass parsed['message'] through in the context, and in the LockFailed branch decide by the errno in the message instead of assuming permissions: ENOSPC 28, EDQUOT 122 on Linux / 69 on macOS, EACCES 13, EPERM 1. Matching the number rather than the strerror text matters because strerror is localized — under a German locale that line reads "Der Speicherplatz auf dem Datenträger wurde überschritten". Note that for a remote repository the errno comes from the server, so the client's own platform constants can't be used for the comparison.

And regardless of the branch, showing Borg's original message as detailed text on the dialog. That alone would have saved me the detour.

For the storage-full case it would also help to say that pruning won't work either and space has to be freed outside the repository.

Happy to open a PR if you agree with the approach.

Reproduction

  • I tried to reproduce the issue.
  • I was able to reproduce the issue.

Fill a repository's backing storage (or set a filesystem quota below what the repo needs) and start a backup from Vorta.

OS

Arch Linux, kernel 7.1.5-arch1-1, KDE Plasma

Version of Vorta

0.11.5 (distribution package vorta 0.11.5-2)

What did you install Vorta with?

Distribution package

Version of Borg

1.4.5

Logs

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

Platform: Linux infinityp10 7.1.5-arch1-1 #1 SMP PREEMPT_DYNAMIC Sun, 26 Jul 2026 00:49:06 +0000 x86_64
Linux: Unknown Linux
Borg: 1.4.5  Python: CPython 3.14.6 msgpack: 1.1.2 fuse: pyfuse3 3.5.0 [pyfuse3,llfuse]
sys.argv: ['/usr/bin/borg', 'info', 'ssh://user@example-storage.invalid:23/./repo']
SSH_ORIGINAL_COMMAND: None

Related

#2341 reports the same dialog for an unmounted drive. There the cause really is [Errno 13], so the wording is at least accurate — this one is about the wording being wrong.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions