My MacBook Air (M3, 8 cores, 16 GB) had been noticeably sluggish for days. Fans don’t exist on this machine, so the only signals were a warm chassis, a laggy UI and a load average that never came down. A quick look at top pointed at a process most people never think about: fileproviderd.
What followed was a few hours of digging through File Provider dumps, consistency checks and Google Drive logs. The root cause turned out to be self-inflicted: roughly 330,000 files of Git repositories, node_modules, Python venvs and Rust build output living inside the Google Drive folder. The sync database had collapsed under it.
This post covers where the errors are visible, why this setup is a bad idea, and how I moved everything out without breaking absolute paths, Claude Code sessions or Codex sessions.
The Symptom: Constant CPU Load
The first snapshot, sorted by CPU:
samuel.heinrich@ ~ % top -l 2 -n 20 -o cpu -stats pid,command,cpu,mem,time,state
Load Avg: 15.46, 17.21, 14.16
CPU usage: 55.75% user, 15.86% sys, 28.37% idle
PID COMMAND %CPU MEM TIME STATE
1131 fileproviderd 173.2 577M+ 103 hrs running
11515 Google Drive 79.0 137M+ 04:34.62 running
1111 suggestd 65.9 29M+ 33:17:41 running
612 WindowServer 49.3 1729M+ 31:35:42 sleeping
0 kernel_task 17.9 32M- 17:45:13 running
samuel.heinrich@ ~ % uptime
21:58 up 8 days, 9:55, 10 users, load averages: 15.46 17.21 14.16
Two numbers stand out:
- A load average of 15–17 on an 8-core machine.
fileproviderdhad accumulated 103 hours of CPU time in 8 days of uptime. That is more than half a core, permanently, for a background daemon. A few minutes later it peaked at 276%.
fileproviderd is the macOS daemon behind the File Provider framework. On current macOS versions, Google Drive for desktop, OneDrive and iCloud Drive all sync through it. Files live under ~/Library/CloudStorage/, and fileproviderd keeps a local database that reconciles the file system with the provider’s cloud state.
samuel.heinrich@ ~ % ls ~/Library/CloudStorage/
GoogleDrive-
<account>@gmail.com
OneDrive-
<org>
So the question was: what is the File Provider trying to sync, and why does it never finish?
Where the Sync Errors Show Up
There are three places worth looking at. None of them are visible in the Google Drive UI, which just shows a spinning sync icon.
1. fileproviderctl dump
fileproviderctl ships with macOS. dump writes the complete daemon state, including every pending sync job:
samuel.heinrich@ ~ % fileproviderctl dump > fpdump.txt
samuel.heinrich@ ~ % wc -l fpdump.txt
1912550 fpdump.txt
Almost two million lines. Domain and file names are obfuscated (g{26}2 (f{14}l.com)), so first find the section of the right provider:
samuel.heinrich@ ~ % grep -nE "^(com|us)\.[a-zA-Z]" fpdump.txt
9:com.apple.CloudDocs.iCloudDriveFileProvider
14291:com.apple.Photos.PhotosFileProvider
14404:us.electronic.macdroid.mountprovider
14448:com.google.drivefs.fpext
1871724:com.microsoft.OneDrive.FileProvider
Pitfall: my first quick look found 65 sync errors dating back to March 2024 and I blamed Google Drive. They belonged to the iCloud Drive domain, which comes first in the dump. Always check which provider block an error belongs to.
The Google Drive block, sync engine state:
sync engine state:
+ upload progress: ... Fraction completed: 0.9946 / Completed: 67206662327 of 67573568200
+ domain version: 3207
+ scheduling state: running
+ error generation: 6346
+ disk import: no
+ stream reset: yes
- scheduler: <l:com.apple.fileproviderd.stream-reset ⏳ registration:<from:2026-10-03 17:29:11 +0000 count:168> ...
error generation: 6346: the sync engine has gone through thousands of error cycles.stream reset: yeswithcount:168: the change stream betweenfileproviderdand the Google Drive extension was reset 168 times in a few hours. Every reset means re-enumerating the domain, in this case 67 GB.
The individual jobs show what is stuck. Three patterns dominated:
⬆︎⬇︎ <fs:⏳ fileID(1198164) delete:ready|recursive|parentDeleted content:watch sver:fileID(1190481)/w{2}e cver:1198164 domver:2853 ⧗recursiveDeletionBackOff> <-> <fp:✅ 1462 fields:structure content:watch sver:2 cver:> dir
⬆︎ <fs:⏳ docID(379191) fields:parentID|structure content:watch sver:fileID(87316600)/0{12}1.txt cver:87316875@4:sz:2004 domver:3207 ⧗parentCreation> <-> <fp:✅ 527795 content:watch sver:24 ...> doc
modifyItem:baseVersion:changedFields:contents:options:request:completionHandler: (no timeout), no progress
recursiveDeletionBackOff: a local deletion that should be propagated to the cloud, now in back-off.parentCreation: an item waiting for its parent folder to be created first.modifyItem … no progress: calls into the Google Drive extension that never return.
Counting them in the Google Drive block:
samuel.heinrich@ ~ % grep -c recursiveDeletionBackOff fpdump.txt
56092
samuel.heinrich@ ~ % grep -c parentCreation fpdump.txt
66376
More than 122,000 stuck items. That is not a backlog that clears itself.
2. FPCK: the File Provider consistency check
fileproviderctl check runs FPCK, a read-only consistency check of the domain database against the file system. repair exists as well, but I did not use it.
samuel.heinrich@ ~ % fileproviderctl check -P -v \
-a "$HOME/Library/CloudStorage/GoogleDrive-
<account>@gmail.com" -o fpck.txt
💣 FPCK failed completing: Error Domain=FPCKDomain Code=65 "(null)"
The check itself aborted. The partial report still says enough:
numberOfBrokenFilesInFSAndFSSnapshotCheck: 140000
numberOfBrokenFilesInReconciliationTableCheck: 36000
numberOfBrokenFilesInFSSnapshotAndFPSnapshotCheck: 110
pendingSetErrors: {"FPCKPendingSetInternalErrorDomain;8":[{"count":55000,"direction":1, ...
db_error_retry_count: 233
About 140,000 inconsistencies between the file system and the database snapshot, 36,000 in the reconciliation table, 55,000 in the pending set. The database is beyond saving.
3. Google Drive’s own log
Google Drive writes a plain-text log:
samuel.heinrich@ ~ % ls ~/Library/Application\ Support/Google/DriveFS/Logs/
drive_fs.txt structured_log_... structured_log_global ...
On startup it lists previous crash reports:
drive_fs_main.cc:221:LogExistingCrashReports 2026-09-29T01:13:52.000Z uuid=03b1... uploaded=1
drive_fs_main.cc:221:LogExistingCrashReports 2026-09-29T08:55:40.000Z uuid=b527... uploaded=1
drive_fs_main.cc:221:LogExistingCrashReports 2026-09-29T09:49:24.000Z uuid=0a3a... uploaded=0
...
Grouped by day:
samuel.heinrich@ ~ % grep LogExistingCrashReports drive_fs.txt | awk '{print substr($4,1,10)}' | sort | uniq -c
1 2026-09-15
2 2026-09-16
3 2026-09-27
5 2026-09-28
6 2026-09-29
2 2026-09-30
5 2026-10-01
24 crashes in less than three weeks, recently up to six per day. Each crash tears down the extension, and fileproviderd answers with a stream reset. That explains the 168 resets.
The most frequent error over 30 minutes:
2128 change_handler.cc:N:PopulateTimeChange Invalid timestamps requested: Is create request: false,
Create: false, Modification: false, Last used: true
These are modify requests in which only the last used date changed. Most likely a local process opened the files (Spotlight, Finder and suggestd were all busy), the timestamp change became a sync job, and Google Drive rejected it. More noise on a queue that is already stuck.
Later, under load, the log also showed hung threads and stalled transfers:
crashpad_thread_watcher_listener.cc:35:ThreadsStuck One or more threads appear to be stuck. Capturing a dump ...
curl_api.cc:N:StatusFromCurlCode Remapped curl code 28 to drive::ds::Status::TIMEOUT_EXCEEDED: Operation too slow.
absl_status_utils.cc:N:UNKNOWN INTERNAL: Unknown Apiary reason [conditionNotMet]. Location was [drive.googleapis.com].
The network was fine (21 MB/s to Google in a parallel test). The client simply could not keep up with its own queue.
Root Cause: 330,000 Files That Never Sit Still
The stuck items pointed to one folder: My Drive/0004_git, where all my Git repositories lived. Counting what was in there:
samuel.heinrich@ ~ % cd ~/Library/CloudStorage/GoogleDrive-</account>
<account>@gmail.com/My\ Drive
samuel.heinrich@ My Drive % python3 dataless.py 0004_git
files=328946 dirs=23945 dataless_files=23273 dataless_dirs=0 local_size=80.4GB
0004_git: .git=32 node_modules=30 .venv=7
files in node_modules: 119042
The biggest offenders:
| Path | Size | Files |
|---|---|---|
public/transferbuddy/target (Rust build output) |
57.2 GB | 155,091 |
videos/.../_audio_analysis/.venv |
1.1 GB | 22,574 |
public/globivonnairobi/node_modules |
535 MB | 30,496 |
13 × identical node_modules in video projects (~5,300 files each) |
~1 GB | ~69,000 |
public/netmon/.build (Swift) |
312 MB | 2,000 |
Why this breaks a File Provider
Google Drive is designed for documents. A file is created, edited a few times, maybe renamed. Each of those events becomes exactly one sync job.
Development folders behave completely differently:
npm install/pnpm installcreates and deletes tens of thousands of small files in seconds.cargo buildrewritestarget/debug/incremental/*on every build. Old session directories are deleted and new ones created.git checkout,git gcandgit fetchreplace objects and pack files.- Python venvs are recreated wholesale.
For fileproviderd, every one of these operations is a separate create, modify or delete job that has to go through the Google Drive extension, to the Drive API and back. None of this content needs to be in the cloud: it can be regenerated, or it already lives on GitHub/GitLab.
Once the backlog is large enough, a feedback loop starts:
flowchart TD
DEV[npm install / cargo build / git checkout]
FS[Tens of thousands of FS events]
FPD[fileproviderd queues sync jobs]
EXT[Google Drive extension overloaded]
CRASH[Drive crashes or threads hang]
RESET[Stream reset: re-enumerate 67 GB]
STUCK[Jobs pile up in back-off]
DEV --> FS
FS --> FPD
FPD --> EXT
EXT --> CRASH
CRASH --> RESET
RESET --> FPD
FPD --> STUCK
STUCK --> EXT
The result was 122,000 stuck jobs, 168 full re-enumerations per day, 24 crashes and a corrupted database. Once you reach that state, the loop doesn’t end by itself.
Side Quest: Why “Empty Trash” Hung Forever
The move required free disk space: 15 GB free on a 460 GB volume. The obvious first step, emptying the trash, hung in Finder’s “Emptying the Trash…” dialog, which couldn’t be cancelled.
The user trash itself was harmless: 49 items, 38 GB, mostly firmware images, nothing locked or open. The cause was elsewhere. Google Drive’s File Provider domain has its own trash:
samuel.heinrich@ ~ % ls -lt ~/Library/CloudStorage/GoogleDrive-</account>
<account>@gmail.com/.Trash | head -4
drwx------@ 2 samuel.heinrich staff 64 Oct 2 21:42 macos-native-0.2.8
drwx------@ 65535 samuel.heinrich staff 64 Oct 2 17:14 s-hmu3463xf3-1ntmumx-di73p4v96vw4wixvc8iy63fe2
drwx------@ 65535 samuel.heinrich staff 2097120 Oct 2 14:31 s-hmu31pp2kg-07mi54r-eicpiaeekeyp1yemxpe2kgjgc
Rust incremental compilation sessions (s-…), .rlib files and Git pack files, all from the same repository folder. Finder’s Empty Trash also empties the File Provider trashes. Each deletion there has to go through the broken fileproviderd database, so the dialog waits forever.
The workaround was to empty only the local trash, bypassing Finder, and then relaunch Finder to get rid of the dialog:
samuel.heinrich@ ~ % find ~/.Trash -mindepth 1 -maxdepth 1 -exec rm -rf {} +
samuel.heinrich@ ~ % df -h /System/Volumes/Data
/dev/disk3s5 460Gi 375Gi 54Gi 88% 2.6M 562M 0% /System/Volumes/Data
samuel.heinrich@ ~ % killall Finder
I emptied the Google Drive trash on drive.google.com. That is a single server-side operation.
The Fix, Step by Step
The goal:
- Move
My Drive/0004_gitto~/0004_git. - Keep everything working that references the old absolute path: scripts, configs, Claude Code and Codex sessions.
- Throw away the corrupted sync database and start with a clean one.
flowchart LR
A[Inventory] --> B[Delete build dirs]
B --> C[Download cloud-only files]
C --> D[Copy + verify]
D --> E[Rewrite paths]
E --> F[Delete folder on web]
F --> G[Disconnect / reconnect Drive]
G --> H[Symlink old path]
Step 1: Inventory, and the dataless trap
With File Provider, files can be dataless: a placeholder with metadata but no local content. ls -lO shows the flag:
samuel.heinrich@ ~ % ls -lO .../0004_git/private/netdash/.git/HEAD
-rw-r--r--@ 1 samuel.heinrich staff compressed,dataless 21 Sep 4 10:00 .../netdash/.git/HEAD
To move or copy such a file, macOS has to download it first through the provider. If the provider is unhealthy or not running, the copy hangs or fails. So check before you move anything. SF_DATALESS is 0x40000000 in st_flags:
import os, sys
DL = 0x40000000
files = dl = 0
for dp, dn, fn in os.walk(sys.argv[1]):
for f in fn:
files += 1
if os.lstat(os.path.join(dp, f)).st_flags & DL:
dl += 1
print(f"files={files} dataless={dl}")
The result: 23,273 dataless files (7.2 GB) and 80.4 GB of local data, with 54 GB free. A copy was impossible, and a move would have stalled on the placeholders.
Step 2: Delete what can be regenerated
Most of the dataless data (4.1 GB) and most of the file count sat in build directories. I deleted every target, node_modules, .venv/venv and .build directory that contained dataless files. Each one was verified first by a marker file: Cargo.toml next to target, package.json next to node_modules, pyvenv.cfg inside a venv, Package.swift next to .build.
OK 57190.4MB 155091 files ( 3994 cloud) public/transferbuddy/target
OK 1125.5MB 22574 files ( 2674 cloud) videos/.../_audio_analysis/.venv
OK 535.0MB 30496 files ( 2504 cloud) public/globivonnairobi/node_modules
OK 311.9MB 2000 files ( 243 cloud) public/netmon/.build
...
34 directories
| Before | After | |
|---|---|---|
Files in 0004_git |
328,946 | 15,050 |
| Local size | 80.4 GB | 23.0 GB |
| Free disk space | 54 GB | 116 GB |
| Dataless files | 23,273 | 1,557 (2.6 GB) |
Step 3: Download the remaining cloud-only files
The 1,557 remaining placeholders were real content: videos, audio, 3D models, presentations and some Git objects. Reading a file forces the File Provider to materialize it.
The first attempt made no progress for 30 minutes. The log explained why: I had quit Google Drive earlier, but it had been relaunched in the background. When I opened it again, it only logged a double launch:
DFSAppDelegate.mm:287:-[DFSAppDelegate applicationShouldHandleReopen:hasVisibleWindows:] Got double launch
crashpad_thread_watcher_listener.cc:35:ThreadsStuck One or more threads appear to be stuck.
It was still pushing the deletions from step 2 to the cloud and had stopped processing downloads. After force-quitting and restarting Drive, a parallel read with a per-file timeout worked:
def get(p):
subprocess.run(["cat", p], stdout=subprocess.DEVNULL, timeout=900)
return p, not (os.lstat(p).st_flags & 0x40000000)
with ThreadPoolExecutor(16) as ex:
for p, ok in ex.map(get, paths):
...
finished ok=1539 bad=6
Four tiny files stayed dataless even though cat returned their content. Two large videos timed out. More on that below.
Step 4: Copy instead of move, then verify
With 116 GB free, copying was now the safer option: the original stays untouched until the copy is verified. ditto preserves permissions, extended attributes and timestamps:
samuel.heinrich@ ~ % ditto ".../My Drive/0004_git" ~/0004_git
ditto stalled after 541 MB of a 1.2 GB video. I resumed with a per-file loop that skips files already copied (same size and mtime) and runs a ditto per file with a timeout. That surfaced two gotchas:
- Dangling symlinks: pnpm workspaces use symlinks into the root
node_modules, which I had just deleted.dittorefuses them (Cannot get the real path for source). I recreated them withln -s "$(readlink src)" dst. dittofollows a symlink passed as the source argument. Per-file copying turned 11 symlinks, such as pnpm workspace links andVersions/Currentinside a.framework, into real directories. I replaced them with the original symlinks afterwards.
Verification compared every entry, checked for leftover placeholders and ran git fsck on every repository:
source entries=15050 missing=3 size_mismatch=0 dataless_in_copy=0 extra_in_copy=0
MISSING clones/ftpmap/__MACOSX/MacOS/._.DS_Store
MISSING clones/ftpmap/__MACOSX/MacOS/build/._.DS_Store
MISSING videos/.../00_Network_Engineers_4k_20260929T103833203Z.mp4
samuel.heinrich@ 0004_git % find . -name .git -not -path "*/node_modules/*" | while read g; do
git -C "$(dirname "$g")" fsck --no-dangling --connectivity-only >/dev/null && echo "OK $(dirname "$g")"
done
OK ./arduino/c6-huso/third_party/esp32-doom
OK ./clones/certctl
...
OK ./web/kisound
All 32 repositories passed git fsck. The two ._ files are AppleDouble leftovers from an extracted ZIP archive, which ditto presumably folded into extended attributes. The only real loss was one rendered 4K video, which can be regenerated. One stuck .gitignore I restored with git checkout -- docugenerator/.gitignore.
Step 5: Rewrite absolute paths
The old path appeared in more places than expected:
| Location | References |
|---|---|
Claude Code project dirs ~/.claude/projects/ |
18 dirs, 24 sessions |
~/.claude.json (project settings, trust) |
13 projects |
~/.claude/history.jsonl (prompt history) |
522 entries |
Codex sessions ~/.codex/sessions/**/*.jsonl |
33 files |
~/.codex/config.toml ([projects."…"] trust) |
11 |
~/.codex/history.jsonl, .codex-global-state.json |
2 |
~/.zshrc (source …/kisound-render.zsh) |
1 |
~/.gitconfig (safe.directory) |
3 |
| Code, docs, manifests | 210 in 60 files |
Before touching anything, I backed up all affected files to ~/path-migration-backup-20261004/. I also quit Codex completely: its background app-server daemon keeps state in memory and would have overwritten the changes.
Claude Code stores sessions in a directory named after the working directory, with every non-alphanumeric character replaced by -:
/Users/samuel.heinrich/Library/CloudStorage/GoogleDrive-</account>
<account>@gmail.com/My Drive/0004_git/blog/show-run.ch
-> -Users-samuel-heinrich-Library-CloudStorage-GoogleDrive-</account>
<account>-gmail-com-My-Drive-0004-git-blog-show-run-ch
/Users/samuel.heinrich/0004_git/blog/show-run.ch
-> -Users-samuel-heinrich-0004-git-blog-show-run-ch
The migration renamed the directories and replaced both the plain path ("cwd":"…") and the encoded directory name inside the session files. ~/.claude.json was rewritten only after checking that no new project key would collide with an existing one, and every JSON, JSONL and TOML file was parsed again before it was written back.
In the code there were three variants of the old path, all mapped to /Users/samuel.heinrich/0004_git:
/Users/samuel.heinrich/Library/CloudStorage/GoogleDrive-</account>
<account>@gmail.com/My Drive/0004_git
/Users/samuel.heinrich/Library/CloudStorage/GoogleDrive-</account>
<account>@gmail.com/My%20Drive/0004_git
/Users/samuel.heinrich/Google Drive/My Drive/0004_git (pre-File-Provider legacy path)
A final check confirmed that 65 of 66 known project and working directories exist at the new location. The missing one was inside a node_modules folder.
Step 6: Delete the folder on the web, then reset the sync database
Deleting 15,000 files locally would have sent them through the broken database again. Deleting the folder on drive.google.com is a single server-side operation, and it stays in the Drive trash for 30 days as an extra backup.
Then Settings → Disconnect account. Drive first checks for unsynced files:
Save unsynced files?
You still have 101 files syncing. Disconnecting might result in losing 101 offline files.
101 unsynced files, 0 bytes
Before confirming, I checked that no local, non-placeholder file outside the old repo folder had changed in the last 7 days. Only .DS_Store files had. The export of the “unsynced files” failed, and the log shows why:
cello_shim.cc:453:CopyPendingUploadItemInternal Failed to copy file to destination:
.../Google Drive (Not synced)/Meine Ablage/0004_git/public/transferbuddy/target/debug...
110 0004_git/public/transferbuddy/target/debug
92 0004_git/public/globivonnairobi/node_modules/.pnpm
0 anything else
They were all pending uploads from the build directories deleted in step 2, so Delete unsynced files was the right choice. The app then hung on “syncing”, so I force-quit it. Afterwards the domain was gone and fileproviderd dropped to idle:
samuel.heinrich@ ~ % for i in 1 2 3 4 5 6; do sleep 10; echo "$(date +%T) fileproviderd: $(ps -o %cpu= -p $(pgrep -x fileproviderd))%"; done
09:22:48 fileproviderd: 0.0%
09:22:58 fileproviderd: 0.0%
09:23:09 fileproviderd: 0.0%
09:23:19 fileproviderd: 0.0%
09:23:29 fileproviderd: 0.0%
09:23:39 fileproviderd: 0.0%
macOS kept the old local content in a preserved folder, . It contained 634 files, mostly fragments of the old repository folder. By the time I signed in again, the folder had been emptied and marked with .drive_fs_ignore_preserved_domain, and the Drive log reported:
file_provider_activity_monitor.cc:618:NotifyReimportCompleted Reimport completion initiated by the system received for item id: root
client.cc:1653:operator() No preserved domains found.
Spot checks confirmed that the files from the preserved folder exist in the new domain.
Step 7: A symlink for the old path, tested first
I wanted the old path to keep working as a safety net. Before pointing a symlink at 23 GB of repositories, I tested how Google Drive treats symlinks with a dummy:
samuel.heinrich@ ~ % mkdir ~/symlinktest-gdrive && echo test > ~/symlinktest-gdrive/hello.txt
samuel.heinrich@ ~ % ln -s ~/symlinktest-gdrive ".../My Drive/_symlinktest"
In the File Provider dump, the link shows up as a single lnk item of 41 bytes, which is the length of the target path. It is synced on both sides, and hello.txt appears nowhere:
<fs:✅ fileID(104459974) ... sver:fileID(104456159)/_{10}t ...> <-> <fp:✅ 13257 ...> symlink
<s:fileID(104459974) p:fileID(104456159) n:"_{10}t" lnk sz:41 m:rwx ...>
Google Drive stores the symlink itself and does not follow it. Then the real link:
samuel.heinrich@ ~ % ln -s /Users/samuel.heinrich/0004_git ".../My Drive/0004_git"
samuel.heinrich@ ~ % ls -la ".../My Drive/0004_git"
lrwxr-xr-x@ 1 samuel.heinrich staff 31 Oct 4 09:29 .../My Drive/0004_git -> /Users/samuel.heinrich/0004_git
Before vs. After
Before, with the old domain:
Load Avg: 15.46, 17.21, 14.16
PID COMMAND %CPU MEM TIME STATE
1131 fileproviderd 173.2 577M+ 103 hrs running
11515 Google Drive 79.0 137M+ 04:34.62 running
After, with the new domain, signed in, and folders being made available offline in the background:
load averages: 5.88 5.05 5.02
PID COMMAND %CPU TIME STATE
612 WindowServer 37.5 33:30:19 sleeping
81473 Google Chrome He 18.0 08:18.03 running
84553 Google Drive 11.4 03:08.52 sleeping
1575 Terminal 9.8 53:27.59 sleeping
0 kernel_task 8.4 21:35:03 running
fileproviderd no longer appears in the top 8.
| Metric | Before | After |
|---|---|---|
| Load average (8 cores) | 15–17 | ~5 |
fileproviderd CPU |
170–276% | not in top 8 (0.0% while no domain was active) |
| Google Drive CPU | 80–100% | ~11% |
error generation |
6,346 | 3 |
| Stream resets | 168 in a few hours | none |
Stuck deletions (recursiveDeletionBackOff) |
56,092 | 0 |
| FPCK inconsistencies | ~140,000 | fresh database |
Files from 0004_git in Drive |
328,946 | 1 symlink |
| Free disk space | 15 GB | 121 GB |
While the new domain was downloading folders I had marked available offline, fileproviderd briefly went up to ~95% again. That is expected during an initial download and drops back down afterwards. The difference is that the work now has an end.
Conclusion
The File Provider framework works well for what Google Drive is built for: documents. It is the wrong place for development folders. Every npm install, cargo build or git checkout becomes thousands of sync jobs. At some point the extension crashes, fileproviderd resets the stream, and the database corrupts under a backlog it can never finish.
What I take away from this:
- Code belongs in Git, not in a sync client. Keep repositories in a local folder such as
~/devor~/0004_gitand back them up through GitHub/GitLab and Time Machine. fileproviderctl dumpandfileproviderctl checkreveal what the sync UI hides. Look forerror generation,stream reset,recursiveDeletionBackOffandparentCreation, and check which provider block they belong to.- Check for dataless files (
ls -lO,st_flags & 0x40000000) before moving anything out of~/Library/CloudStorage/. - Delete large folders on the web, not locally, when the local client is already struggling.
- A corrupted domain doesn’t recover by itself. Disconnecting and reconnecting the account is the clean reset.
- Absolute paths are everywhere, including AI tooling. Claude Code encodes the working directory in its project directory names, and Codex stores it in every session file. Back them up and quit the apps before rewriting.
Download als PDF File