nextcloud / nextcloud/desktop

Windows: "Rename file" dialog fails with "Source file does not exist" - FileSystem::rename() computes longWinPath() but does not use it

Open
#10,836 0 comments 0 reactions 1 assignee Claimed by @claucambra View on GitHub
0. Needs triage bug
Dominant language
C++
Stars
3.9k
Forks
1k
Avg merge
1d 17h
Merged PRs (30d)
123

Description

### ⚠️ Before submitting, please verify the following: ⚠️

- [x] This is a **bug**, not a question or a configuration issue.
- [x] This issue is **not** already reported on Github (I have searched for it).
- [x] Nextcloud Server and Desktop Client are **up to date**. See [Server Maintenance and Release Schedule](https://github.com/nextcloud/server/wiki/Maintenance-and-Release-Schedule) and [Desktop Releases](https://nextcloud.com/install/#install-clients) for supported versions.
- [x] I agree to follow Nextcloud's [Code of Conduct](https://nextcloud.com/contribute/code-of-conduct/)

### Bug description

On Windows, the desktop client resolves local files through ordinary Win32 paths. Win32
strips trailing spaces and trailing periods from a path before it reaches the filesystem,
so a file whose name ends in either character cannot be addressed that way. NTFS stores
such names without complaint — only the path layer refuses to carry them.

Two failures follow from this.

**1. Trailing period — the offered remedy cannot work.**

The client reports the file properly: a named warning with a "Rename file" button. The
dialog then fails with *"Could not rename local file. Source file does not exist."* The
file does exist; the client is looking for it by a path Win32 has already trimmed.

```
[ warning nextcloud.sync.filesystem src\common\filesystembase.cpp:230 ]:
Error renaming file "D:/benth/_NcBug/trailing period." to "D:/benth/_NcBug/no trailing period"
failed: "Source file does not exist."
```

This matters because File Explorer cannot fix such a name either, for the same reason.
The button is the user's only obvious route out, and it is a dead end.

The cause is visible in `src/common/filesystembase.cpp` at v34.0.3. `FileSystem::rename()`
computes the long-path forms and then uses them only in the `.lnk` branch:

```cpp
209 QString orig = longWinPath(originFileName);
210 QString dest = longWinPath(destinationFileName);
211
212 if (isLnkFile(originFileName) || isLnkFile(destinationFileName)) {
213 success = MoveFileEx((wchar_t *)orig.utf16(), // uses them
214 (wchar_t *)dest.utf16(),
215 MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH);
...
219 } else
220 #endif
221 {
222 QFile orig(originFileName); // does not
223 success = orig.rename(destinationFileName);
```

`longWinPath()` is `pathtoUNC()` on Windows, i.e. the `\?\` form that turns off Win32
path parsing. For every file that is not a shortcut, lines 209-210 are dead and the raw,
trimmable strings are used instead. The same file calls `longWinPath()` correctly in nine
other places, so this reads as an overlooked call rather than a deliberate choice.

**2. Trailing space — the local file is renamed without the user being told.**

The client renames the file on disk (`ProcessDirectoryJob::maybeRenameForWindowsCompatibility`)
and uploads it under the trimmed name, which succeeds. What the GUI reports, however, is a
failure: a tray notification and a sync error reading *"Filename contains trailing spaces."*
for the original name — a name that no longer exists on disk by the time the message is
shown. Server-side Activities separately records "You created ``" as an
ordinary creation.

Nowhere does the interface state that a local file was renamed. The user is shown an error
for an operation that in fact succeeded, and a creation entry for a name they never chose;
nothing connects the two. Establishing what actually happened requires running the client
with `--logdebug` and reading the sync log, which is not a reasonable expectation of a user
whose file has just been modified.

I am aware of #7668, which specifies that the windows-compatible-filenames rename happens
without a user dialog. This report does not ask for that dialog back — only that the change
be recorded where the user can see it.

### Steps to reproduce

File Explorer cannot create these names, but an application can. Create them through the
raw path, in a folder that is a sync pair with virtual files disabled:

```powershell
$root = 'C:\path\to\syncfolder'
[System.IO.File]::WriteAllText("\?\$root\trailing space ", "x")
[System.IO.File]::WriteAllText("\?\$root\trailing period.", "x")
[System.IO.File]::WriteAllText("\?\$root\ leading space.txt", "x")
[System.IO.File]::WriteAllText("\?\$root\.leading period.txt", "x")
```

Let the client sync.

1. `trailing period.` → warning shown. Click "Rename file", enter any new name, click OK
→ *"Could not rename local file. Source file does not exist."*
2. `trailing space ` → renamed on disk to `trailing space` and uploaded successfully, while
the GUI reports *"Filename contains trailing spaces."* as a failure. No message anywhere
says the local file was renamed.
3. The two leading-character files are the control: both sync untouched.

### Expected behavior

- The "Rename file" dialog should be able to rename the file it is offered for.
- When the client renames a local file itself, it should say so — in the error/activity list
rather than only in the debug log — and the message shown should not describe a failure
when the file was in fact synced under a changed name.

### Which files are affected by this bug

`trailing period.` and `trailing space ` (also `Efterfoelgende punktum.`, `Efterfoelgende mellemrum `)

### Operating system

Windows

### Which version of the operating system you are running.

Windows 11 Pro 26200 (25H2), `LongPathsEnabled = 1`

### Installation method

Official Windows MSI

### Nextcloud Server version

33.0.9 (hosted)

### Nextcloud Desktop Client version

33.0.9 (hosted)

### Did this occur after an update or on a clean installation?

Clean desktop client installation

### Are you using the Nextcloud Server Encryption module?

No

### Are you using an external user-backend?

- [x] Default internal user-backend
- [ ] LDAP or Active Directory
- [ ] SSO - SAML
- [ ] Other

### Nextcloud Server logs

```shell

```

### Additional info

**Control test.** This is about position, not the character. `" leading space.txt"` and
`".leading period.txt"` both sync untouched and are reachable through a normal Win32 path:

```
PUT of ".../_NcBug/ leading space.txt" FINISHED WITH STATUS "OK" 201 "Created"
PUT of ".../_NcBug/.leading period.txt" FINISHED WITH STATUS "OK" 201 "Created"
```

Win32 trims only at the end of a name, so the client handles one end correctly and breaks
on the other, purely as a consequence of which path form it uses.

**Measured on the affected file:**

```powershell
[System.IO.File]::Exists('C:\path\trailing period.') # False
[System.IO.File]::Exists('\?\C:\path\trailing period.') # True
[System.IO.Path]::GetFullPath('C:\path\trailing period.') # -> 'C:\path\trailing period'
```

**Prior issues searched.** #4387, #4390, #3749, #6961, #2651 all cover trailing spaces and
are closed as completed; #6760 covered earlier defects in this same dialog and is closed;
#7668 is the design decision behind the automatic rename. #8108 (open) is a separate defect
in the same dialog — no debounce on the OK button. None of them covers the rename dialog
failing on a path Win32 has trimmed.

**Related.** The same dialog also builds its remote PROPFIND URLs without a path separator;
reported separately as #10837.

**Log.** Trimmed excerpt attached (client run with `--logdebug --logflush`).

[Nextcloud-issue-log-excerpt.log](https://github.com/user-attachments/files/32253337/Nextcloud-issue-log-excerpt.log)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.