nextcloud / nextcloud/desktop

VFS (cfapi) sync engine treats transient local I/O errors as file deletion, propagating mass deletion to server without confirmation

Open
#10,456 1 comment 0 reactions 1 assignee Claimed by @camilasan View on GitHub
bug os: :door: Windows
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

# VFS (cfapi) sync engine treats transient local I/O errors as file deletion, propagating mass deletion to server without confirmation

## Environment
- **Desktop client:** 33.0.7 (Windows)
- **Server:** Nextcloud 32
- **Sync mode:** Virtual Files (`virtualFilesMode=wincfapi`), sync root = `/` (entire account root synced)
- **Relevant client config (`nextcloud.cfg`):**
```
promptDeleteAllFiles=false
moveToTrash=false
```
- **Auth:** webflow, backend AD (Samba4 DC) — see "What we ruled out / narrowed down" below for how this fits in

## Summary

During a routine sync, the Windows Cloud Filter API (CfAPI) returned a transient I/O error while the client was reading the state of local VFS placeholders. The sync engine interpreted this I/O error as "file no longer exists locally," concluded the user had deleted the files, and propagated a **real deletion to the server** for several thousand files across the entire sync root — with **no confirmation prompt**, even though a large-scale deletion safety net (`promptDeleteAllFiles`) exists in the codebase. The admin was able to fully recover all affected files after the fact; no permanent loss occurred in this instance, but only because the deletion was caught and reverted quickly, not because of any safeguard in the client itself.

## Evidence, in chronological order (all timestamps local, from client debug log)

**1. First discovery pass fails with mass CfAPI I/O errors**
```
08:45:16.296 → 08:45:19.276 [critical] csync_vio_local_win.cpp:202
CreateFileW failed on "\"
WindowsError: -7fe0fffb: An invalid name request was made.
The name requested cannot be retrieved at this time.
```
This error (`0x801F0005` as unsigned 32-bit) recurs **1,838 times** in ~3 seconds, against placeholder files under the synced root.

```
08:45:21.381 Discovery end .... 52249 ms
08:45:21.381 Restarting sync as discovery results might be incomplete.
08:45:21.382 [warning] localdiscoverytracker.cpp:84
sync failed, keeping last sync's local discovery path list
```

**2. Second discovery pass — client forces a raw filesystem-only rescan, same errors continue**
```
08:45:32.917 Forbidding local discovery to read from the database (folder.cpp:1214)
08:45:32.917 Sync started for folder [C:\NC]
08:45:32.932 Discovery start
08:46:25.878 Discovery end .... 52945 ms
```
Same `CreateFileW` / `-7fe0fffb` critical error recurs **340 + 1,901 = 2,241 more times** during this second pass (total across both passes: **4,079 occurrences**).

**3. Placeholder creation fails at the exact moment deletion propagation begins**
```
08:46:26.218 [critical] bulkpropagatordownloadjob.cpp:90
Could not create placholders: "Couldn't create placeholder info"
08:46:26.234 [critical] same error
08:46:26.306 [info] permanent_delete log — propagateremotedelete.cpp:24
delete "" ... (72ms after the last placeholder-creation failure)
```
Discovery item records for the deleted files show the local side was marked invalid while remote state was inherited from the local DB cache rather than freshly verified:
```
Processing "" | (db/local/remote)
valid: true/false/db
mtime: /0/0 size: /0/0 etag: ""//""
type: ItemTypeVirtualFile/ItemTypeSkip/ItemTypeFile
```

**4. Cascade continues for ~2 minutes**, producing 60+ rotated `permanent_delete.log.N` files and deleting several thousand files across the entire synced tree, until the user manually stopped the client (client logs end abruptly ~10:17, config shows `paused=true` afterward).

## What we ruled out / narrowed down
- **Server-side application auth was not the trigger:** every LDAP bind performed by the Nextcloud server's user backend for the affected account, checked directly on the domain controller for the whole incident window, returned `NT_STATUS_OK`. This path (Nextcloud server ↔ DC) was healthy throughout.
- **Antivirus:** confirmed disabled on the client machine at the time — not the cause of the CfAPI errors.
- **Duplicate account entry** the user noticed shortly before (a known separate client quirk after webflow re-login) — occurred ~1 minute before this window; not proven to be the trigger, may be a parallel symptom of the same underlying disruption.

## A distinct, client-machine-local signal we found (not yet confirmed as causal)
Separately from the (healthy) server↔DC path above, the Windows Event Log **on the affected client machine itself** shows something odd in the *same* 2-second window as the second CfAPI error burst:
```
06:46:36–38 UTC Microsoft-Windows-NlaSvc, Event 4343 (LdapAuthenticationFailed task)
ErrorCode 2684880071 (0xA00804C7), then ErrorCode 81 (0x51 = LDAP_SERVER_DOWN)
06:46:37.191 UTC Microsoft-Windows-WFP, Event 1030
TxnTimeInMSec: 1297, WatchdogTimeoutInMSec: 500
```
This is the machine's own periodic "am I on the domain network" check (unrelated to the Nextcloud app-level auth above), and it failed with a server-unreachable error, coincident with a brief (~1-2s) stall in the machine's network filter stack. One domain controller happened to be down for planned maintenance at an unconfirmed but plausibly overlapping time, which would be a plausible explanation for this specific local NLA failure if the client machine's DC-locator briefly tried the offline DC. **We have not been able to confirm the exact overlap in timing**, so we're not asserting this as the confirmed cause of the CfAPI errors — only flagging it as a coincident, unexplained local network hiccup that Nextcloud engineers may want to know about, in case it's relevant to reproducing CfAPI's error path.

## The actual bug we're reporting

Regardless of what causes the transient local read failure (network hiccup, disk contention, driver flakiness — all things that *will* happen occasionally in production fleets), **the sync engine should not be able to conflate "I got an I/O error reading this placeholder" with "this file is confirmed absent locally."** These are different conditions:
- A `CreateFileW` failure is explicit evidence the client *could not determine* the file's state.
- Only a clean "not found" result is evidence of actual absence.

Currently, an I/O error during discovery appears to fall through to the same deletion-propagation path as a genuine local deletion, and — because `promptDeleteAllFiles` gates confirmation but doesn't gate whether the *decision* to delete is well-founded — a burst of transient I/O errors was enough to trigger mass deletion of files that were never touched by the user.

## Suggested fix directions
1. Discovery should distinguish "local state unknown due to I/O error" from "local item confirmed absent," and skip/retry the former rather than treating it as a delete candidate.
2. If a discovery pass encounters a critical I/O error rate above some threshold (here: 1,838 errors in 3 seconds), the pass should be considered unreliable and the *whole* affected subtree should be re-verified before any deletion decision, not just individual items.
3. `promptDeleteAllFiles` should remain a secondary safety net, but shouldn't be the *only* thing standing between a transient I/O glitch and irreversible propagation to the server — especially with `virtualFilesMode` where the local "absence" of a placeholder is cheap to fake accidentally.

## Related existing issues (feature requests for delete confirmation, worth cross-referencing)
- nextcloud/desktop#478 — "Add configuration options to prompt before file/folder deletion" (explicitly describes this same corrupted-local-storage scenario back in 2018)
- nextcloud/desktop#9292 — "Add delete confirmation dialogs"
- nextcloud/desktop#8831 — "Add a warning/confirmation to prevent mass deletion... when a folder is removed from the server"

## Attachments
Raw client debug logs and the exact file paths affected are available on request; we've redacted internal folder/file names from this report for confidentiality but can provide un-redacted excerpts privately to Nextcloud engineering if useful for reproduction.

### Steps to reproduce

1. Right click on the file
2. Click on Share Options
3. The share dialog does not display the option to share by e-mail
...

### Expected behavior

When clicking on the share dialog, share by e-mail should be an option.
...

### Which files are affected by this bug

2026-07-24 08:46:26:306 [ info nextcloud.log.permanent C:\Users\User\AppData\Local\Temp\windows-40387\client-building\desktop\src\libsync\propagateremotedelete.cpp:24 ]: delete "[NAME]/Commerciale/Ass. Tecnica/Schede intervento/2026/14 - xxxxx/DDT a Fornitore.pdf" "Processing \"[NOME]/Commerciale/Ass. Tecnica/Schede intervento/2026/14 - xxxx/DDT a Fornitore.pdf\" | (db/local/remote) | valid: true/false/db | mtime: 1773138594/0/0 | size: 195385/0/0 | etag: \"a4adab456d8a046fbba2c5c61cb6a1fc\"//\"\" | checksum: \"SHA1:b5a7a924f3e79bdfcdde78b5d36423415ab6980f\"//\"\" | perm: \"GWDNVRm\"//\"\" | fileid: \"04185279ocoa3igv2k1t\"//\"\" | inode: 57103/0/ | type: CSyncEnums::ItemTypeVirtualFile/CSyncEnums::ItemTypeSkip/CSyncEnums::ItemTypeFile | e2ee: false/false | e2eeMangledName: \"\"/\"\" | file lock: not locked// | file lock type: \"\"//\"\" | live photo: false//false | metadata missing: /false/"

### Operating system

Windows

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

Windows 11

### Installation method

Official Windows MSI

### Nextcloud Server version

32.0.9

### Nextcloud Desktop Client version

33.0.7

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

Minor version update (i.e. 33.0.0 → 33.0.1)

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

No

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

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

### Nextcloud Server logs

```shell

```

### Additional info

_No response_

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.