[Bug]: Windows WinCfAPI hydration hangs for online-only files <= 4096 bytes
- Dominant language
- C++
- Stars
- 3.9k
- Forks
- 1k
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 127
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 10 with Virtual Files (WinCfAPI), opening some small online-only files hangs instead of hydrating them.
The issue was originally observed with normal .rdp files around 2.4-2.5 kB. I then reproduced it with synthetic files of exact sizes and found a deterministic boundary:
| File size | Result |
|---|---|
| 4095 bytes | FAIL - read/hydration hangs |
| 4096 bytes | FAIL - read/hydration hangs |
| 4097 bytes | OK - hydrates in ~0.4 s |
| 8192 bytes | OK - hydrates in <1 s |
For the failing files, the Nextcloud client downloads the complete file successfully and logs:
`GETFileJob finished`
followed by:
`Hydration job finished ... OCC::HydrationJob::Success`
However, the Windows CfAPI placeholder remains `Offline` / `RecallOnDataAccess` and the process trying to read the file remains blocked.
About 60 seconds later the client logs:
`Cancel fetch data`
The problem is not specific to Explorer or Total Commander. It was reproduced with a minimal PowerShell/.NET test that opens the file and reads a single byte.
A 4097-byte file created and tested in exactly the same way hydrates successfully.
### Steps to reproduce
1. Configure a sync folder on Windows using Nextcloud Virtual Files (WinCfAPI).
2. Create three files with exact sizes:
- 4095 bytes
- 4096 bytes
- 4097 bytes
3. Let all three files finish syncing to the server.
4. Use "Free up local space" / make them online-only.
5. Verify that each test file is an online-only CfAPI placeholder.
6. Open each file, or perform a minimal read of one byte.
7. Observe:
- 4095 bytes: the read blocks and hydration does not complete.
- 4096 bytes: the read blocks and hydration does not complete.
- 4097 bytes: hydration completes normally.
For the 4096-byte failing case, the HTTP download itself completes in about 80 ms and the client reports `HydrationJob::Success`, but the Windows placeholder remains offline and the caller stays blocked.
Approximately 60 seconds later the client logs `Cancel fetch data`.
### Expected behavior
Online-only files should hydrate successfully regardless of their size.
Files of 4095 and 4096 bytes should behave like the 4097-byte file: the data should be transferred to Windows CfAPI, the placeholder should become hydrated, and the application reading the file should return normally.
### Which files are affected by this bug
Online-only files in a Windows WinCfAPI virtual-files sync. The issue appears to be size-dependent rather than extension-dependent. It was originally observed with .rdp files around 2.4-2.5 kB and reproduced with synthetic .bin files.
### Operating system
Windows
### Which version of the operating system you are running.
Windows 10 Pro 22H2, build 19045
### Installation method
Official Windows MSI
### Nextcloud Server version
33.0.9
### Nextcloud Desktop Client version
34.0.3
### Did this occur after an update or on a clean installation?
Major version update (i.e. 4.0.0 → 33.0.0)
### 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
The exact 4096/4097-byte boundary may be relevant to the WinCfAPI implementation.
The current CfAPI wrapper uses a 4096-byte transfer block:
`constexpr auto cfapiBlockSize = 4096;`
I am not claiming this is necessarily the root cause, but the experimentally observed boundary is exactly between 4096 bytes (fails) and 4097 bytes (works).
For the failing 4096-byte case, the sequence is:
1. CfAPI fetch request received
2. GET starts
3. GET completes successfully (~80 ms)
4. `Hydration job finished ... OCC::HydrationJob::Success`
5. sync journal is updated to `CSyncEnums::ItemTypeFile`
6. Windows placeholder nevertheless remains `Offline` / `RecallOnDataAccess`
7. the requesting process remains blocked
8. roughly 60 seconds later: `Cancel fetch data`
Possibly related:
- #7747 - Windows VFS hydration/open failures
- #4509 - historical size-dependent VFS problem with small files (dehydration rather than hydration)
No relevant server-side error was observed during reproduction. The file GET completes successfully; the failure occurs afterwards in the Windows WinCfAPI hydration path.
Contributor guide
Research direction
Start by locating the WinCfAPI wrapper and the `cfapiBlockSize = 4096` definition, then trace the hydration path after `HydrationJob::Success`. Reproduce the issue with 4095-, 4096-, and 4097-byte online-only files using the described minimal read. Done means the 4095- and 4096-byte placeholders hydrate and the reading process returns normally, without the delayed cancellation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- desktop, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100