fix(core,fuse,cli,gui): refuse to mount My files over a folder with files in it

FUSE mounts over a non-empty folder without complaint, so files already
in the My files folder were hidden under the mount: not uploaded, and
back only once the service stopped, so they looked deleted (#67, B277).

- pdfs-core: new `mountpoint` module. `not_empty` lists what is in a
  folder (hidden entries count); `mounted_fs_type` moves here from the
  CLI so the daemon can use it. `MountFailure` gains an optional
  `not_empty` field, which older readers ignore.
- pdfs-fuse: `mount_with` checks the folder before the root fetch and
  before any worker starts. A dead mount is cleared first; one of our
  own live mounts is left to `spawn_session`, as before.
- pdfs-cli: `cmd_daemon` records the folder in the failure record. The
  refusal backs off and retries like any mount failure, so emptying the
  folder is enough.
- pdfs-gui: the status pages explain the refusal, and a dialog offers
  to open the folder or choose another one, once per run of failures.
  The folder picker refuses a folder with files in it.

Translated in all catalogs. Docs: BUGS (B277), CHANGELOG, FAQ,
TROUBLESHOOTING, CONFIGURATION.
This commit is contained in:
nvrl committed 2026-11-01 15:30:28 +01:00
1 parent 321547fb77
commit 5048492a83
22 files changed
+2105 -1251

No files matched your search

+42
View File
@@ -109,6 +109,7 @@ a live account since.
| Entry | Title |
|---|---|
| [B277](#b277--my-files-mounted-over-a-folder-with-files-in-it-and-hid-them) | My files mounted over a folder with files in it, and hid them |
| [B276](#b276--a-stop-can-end-with-a-panic-in-a-thread-the-stop-never-waited-for) | A stop can end with a panic in a thread the stop never waited for |
| [B274](#b274--opening-a-file-for-writing-fails-with-eio-while-its-queued-revision-lands) | Opening a file for writing fails with EIO while its queued revision lands |
| [B272](#b272--after-a-folder-is-removed-and-added-again-its-file-events-go-to-the-old-id) | After a folder is removed and added again, its file events go to the old id |
@@ -379,6 +380,47 @@ a live account since.
Newest first.
### B277 — My files mounted over a folder with files in it, and hid them
**Status:** Fixed, not verified live
**Found:** 2026-10-31, issue #67. The reporter chose an existing working folder as the My files
location. Its folders disappeared and looked deleted; they came back when the service stopped.
**Where:** `mount_with` and `check_mountpoint` in `crates/pdfs-fuse/src/mount.rs`;
`crates/pdfs-core/src/mountpoint.rs`; `prompt_mountpoint` in
`crates/pdfs-gui/src/app/pages/status.rs`
**Repro:** Stop the service. Put a file and a folder in `~/ProtonDrive`, or choose a folder with
files in it under Preferences → General → Location. Start the service. The files are hidden
under the mount: not uploaded, not in the queue, and back only once the service stops.
**Cause.** FUSE mounts over a folder that is not empty without a word, and nothing checked the
folder first. `mount_once` only created it. On-demand synced folders were already checked when
they were mounted again after a restart (`restore_ondemand_mounts`); My files was not. The
folder picker took any folder.
**Fix.**
- The daemon refuses to mount My files over a folder with anything in it, hidden files
included, before it fetches the root or starts a worker. A dead mount is cleared first, so it
can be listed. One of this client's own live mounts is left to the mount, which clears it as
before.
- The refusal is a mount failure like any other: it backs off and tries again, so emptying the
folder is enough. The failure record now carries the folder and its first entries
(`MountFailure::not_empty`), which an older reader ignores.
- The app explains it in the user's language, and offers to open the folder or choose another
one. The folder picker refuses a folder with files in it.
Merging an existing folder into My files is not done here. #67 proposes `pdfs sync attach` for
that, as a separate change.
**Test:** `a_folder_with_files_is_refused_and_named`, `a_hidden_file_alone_is_enough_to_refuse`,
`an_empty_or_missing_folder_takes_the_mount` in `crates/pdfs-core/src/mountpoint.rs`;
`a_failure_an_older_daemon_wrote_still_reads` in `mountfail.rs`;
`a_mount_refused_over_files_is_recorded_as_such` in `crates/pdfs-cli/src/main.rs`; the
simulation `a_mount_over_local_files_is_refused_and_leaves_them_alone`.
---
### B276 — A stop can end with a panic in a thread the stop never waited for
**Status:** Fixed, not verified live
+7
View File
@@ -13,6 +13,13 @@ scratch (user data in `staging/` and `recovery/` is never touched by this).
### Fixed
- **My files no longer opens over a folder that already has files in it** (#67, B277). The files
were hidden under it, not uploaded, and came back only when the service stopped, so they looked
deleted. The service now waits until the folder is empty, and the app says why and offers to
open the folder or choose another one. The folder picker in Preferences refuses a folder with
files in it. **After upgrading:** if your `~/ProtonDrive` has files underneath, for example
saved there while the service was stopped, My files does not open until you move them out.
- **A new file reads without the network as soon as `pdfs status` shows nothing queued**
(B257). A new file's upload counted as done before its bytes were cached, so a script that
waited for an empty queue and then went offline could not read it. A new file deleted while
+1 -1
View File
@@ -76,7 +76,7 @@ fix it.
| Key | Type | Default | In the app | Meaning |
|---|---|---|---|---|
| `mountpoint` | path | `~/ProtonDrive` | General → Location | Where My files is mounted |
| `mountpoint` | path | `~/ProtonDrive` | General → Location | Where My files is mounted. Must be empty: the service does not mount over files |
| `cache_budget` | bytes | 5 GiB | Storage → Cache | Soft limit for cached content. `0` means unlimited. Available-offline files do not count against it |
| `upload_limit` | bytes/s | none | General → Network | Shared cap for all uploads. `0` or `null` means none |
| `download_limit` | bytes/s | none | General → Network | Shared cap for all downloads, reads from the mount included |
+3 -1
View File
@@ -28,7 +28,9 @@ Yes. `~/ProtonDrive` is your Proton Drive, not a copy. A deleted file moves to t
Trash, and you can restore it from **Trash** in the app or the web. See [Trash](FILES.md#trash).
Stopping the service is not the same: once the service stops, `~/ProtonDrive` is just an empty
folder, and your files stay on Proton Drive.
folder, and your files stay on Proton Drive. Keep it empty: the service does not open My files
over a folder with files in it, because it would hide them. See
[My files does not open: the folder is not empty](TROUBLESHOOTING.md#my-files-does-not-open-the-folder-is-not-empty).
## Online only, available offline or synced folder: which do I want?
+14
View File
@@ -141,6 +141,20 @@ fusermount3 -uz ~/ProtonDrive
systemctl --user restart proton-drive.service
```
### My files does not open: the folder is not empty
The app says **Your Proton Drive Folder Isn't Empty**, and `pdfs diagnose` reports
`mount: failing … is not empty`. The folder chosen for My files has files in it, and the service
does not open My files over them: they would be hidden, and not uploaded, for as long as the
service runs.
Move the files out of the folder, or choose another folder in **Preferences → General →
Location**. The service tries again on its own and opens once the folder is empty. To put the
files on Proton Drive, copy them into My files once it is open.
Files saved into `~/ProtonDrive` while the service was stopped are in the same place: in the
local folder, not on Proton Drive.
### The folder is empty or missing
Check that the service runs and is signed in, with `pdfs status`. The service waits for a stored