[BUG] Desktop (Win): oversized main.log triggers rotation-check loop that never issues the rename — ~8-9% CPU at idle; log lines doubled
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Summary
Claude Desktop's main process consumes a sustained ~8–9% CPU at complete idle (Task Manager Processes tab shows 20–25% due to process-tree grouping and Processor Utility normalization). There are zero data writes to disk while this happens — the burn is pure metadata syscall churn: ~700,000 filesystem events in 30 seconds.
Root cause, established by ProcMon at the syscall level:
- Trigger:
main.logexceeds the 10 MiB rotation threshold (observed file: 10,487,371 bytes; threshold appears to be 10,485,760). - Logic bug: the rotation code completes every preparatory step — stat shows file over threshold, probes
main1.log/main2.log/main3.logfor a free archive slot (all NAME NOT FOUND), opensmain.logwith Delete access + Open Reparse Point, queries attributes — and then closes all handles and restarts the cycle without ever issuing the rename. Across ~700k captured events there is noSetRenameInformationFile, noSetDispositionInformationFile, and no failing operation of any kind — every event returns SUCCESS. This is not an I/O failure being retried; the rename is simply never attempted. - No backoff: the full cycle takes ~0.35–0.5 ms and repeats indefinitely (~2,000+ iterations/sec, ~20,000+ syscalls/sec), keeping 5 libuv threadpool workers + the event loop busy.
- Aggravator (related defect, same init path): the
main.logfile transport is registered twice — every log line is written twice, the process holds three open handles tomain.log, and the rotation-check cycle itself runs twice concurrently (every operation in the trace appears in duplicate). Doubled writes also make the file reach the 10 MiB trigger twice as fast.
Because the failure is pure logic (no environmental dependency — see ruled-out factors below), this should affect any installation once main.log crosses 10 MiB. It may explain a slice of the previously reported vague "desktop app hot when idle" symptoms.
Evidence
Thread signature (Process Explorer, main Claude.exe, no --type= argument): 6 busy threads — 5 libuv threadpool workers + event loop (labeled uv_cond_signal+offset; nearest-export labels, binary exports almost nothing).
Steady-state ProcMon trace — one rotation-check cycle, ~0.5 ms, repeating indefinitely:
<details>
<summary>ProcMon excerpt: one cycle (steady state)</summary>
9:12:33,1506635 Claude.exe CreateFile ...\Claude\logs SUCCESS Desired Access: Write Data/Add File
9:12:33,1507933 Claude.exe CreateFile ...\logs\main3.log NAME NOT FOUND
9:12:33,1508074 Claude.exe CreateFile ...\logs\main.log SUCCESS Read Attributes
9:12:33,1508487 Claude.exe QueryAllInformationFile main.log BUFFER OVERFLOW
EndOfFile: 10 487 371 LastWriteTime: 04.06.2026 ChangeTime: (today)
9:12:33,1509179 Claude.exe CreateFile main2.log NAME NOT FOUND
9:12:33,1509885 Claude.exe CreateFile main3.log NAME NOT FOUND
9:12:33,1510210 Claude.exe CreateFile main1.log NAME NOT FOUND
9:12:33,1511333 Claude.exe CreateFile main.log SUCCESS
Desired Access: Read Attributes, Delete, Synchronize, Open Reparse Point
ShareMode: Read, Write, Delete
9:12:33,1511523 Claude.exe QueryBasicInformationFile main.log SUCCESS
[cycle restarts]
</details>
Controlled re-trigger capture (quit app → place the saved >10 MiB main.log back → relaunch → 30 s ProcMon capture filtered to Path contains main.log): ~700,000 events in 30 seconds. Findings:
- Zero occurrences of
SetRenameInformationFileorSetDispositionInformationFile. - Zero failing operations — every event in the loop returns SUCCESS (the
main1/2/3.logNAME NOT FOUND probes are expected slot checks, not failures). - Every step appears twice back-to-back (two Delete-access opens, two QueryAllInformationFile, paired closes) — two concurrent checker loops, consistent with the duplicate transport registration.
Duplicate transport registration — startup CreateFile events for the (recreated) main.log: three byte-identical append-mode opens, the first two 0.2 ms apart, the third ~350 ms later:
<details>
<summary>ProcMon excerpt: transport opens at startup</summary>
9:53:30,4322214 Claude.exe CreateFile main.log SUCCESS
Desired Access: Append Data/..., Disposition: OpenIf, ShareMode: Read, Write, Delete
9:53:30,4324579 Claude.exe CreateFile main.log SUCCESS (identical parameters)
9:53:30,7855666 Claude.exe CreateFile main.log SUCCESS (identical parameters)
</details>
Corresponding handle64.exe output shows three simultaneous open handles to main.log from the main process, and the log content shows every line duplicated:
2026-07-03 09:20:11 [info] [growthbook] loaded 201 features (0 changed)
2026-07-03 09:20:11 [info] [growthbook] loaded 201 features (0 changed)
2026-07-03 09:20:11 [info] [growthbook] next refresh in 60 min
2026-07-03 09:20:11 [info] [growthbook] next refresh in 60 min
(Exactly doubled — not tripled — lines suggest two live transports; the third handle belongs to a component that opens the file the same way without receiving emits, plausibly the rotation checker.)
Ruled out
- Sharing violation blocking the rename: all handles are opened with
ShareMode: Read, Write, Delete, and in any case no rename is ever attempted. - Filesystem/path environment: my
LocalCacheis relocated via an NTFS junction, but no path-mutating operation is ever issued and nothing fails, so the junction is not a factor. - Disk-write churn (#58799 mechanism): zero data writes during the burn.
- Coder polling (#60024): no workspace-discovery lines in any log.
Workaround / deterministic reproducer
- Quit Claude fully (tray → Quit).
- Move the oversized
main.logout of the logs folder → relaunch → CPU immediately drops to baseline. - Place the oversized file back → relaunch → burn resumes within seconds.
I have kept the >10 MiB file and can re-trigger and capture on demand.
A fresh main.log is recreated and written (at 2× rate due to the duplicate transport), so any install will re-enter the burn state once the file regrows past 10 MiB.
What Should Happen?
- When
main.logexceeds the rotation threshold, the rotation should actually be performed (rename to an archive slot), or — - If rotation cannot or will not proceed, the condition should be treated as terminal for the session (log once, skip/disable), or at minimum back off — not re-run the full check at sub-millisecond frequency.
- The
main.logtransport should be registered once; log lines should not be duplicated.
Error Messages/Logs
Steps to Reproduce
- Use Claude Desktop on Windows until
main.logexceeds 10 MiB (accelerated 2× by the duplicate-write defect), or place any >10 MiBmain.loginto the logs directory. - Launch the app. No interaction needed.
- Observe: main
Claude.exesustained ~8–9% CPU (Details tab), 5 busy libuv threadpool workers, and a ~0.35–0.5 ms rotation-check cycle repeating indefinitely in ProcMon, with no rename ever issued.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude 1.18286.0 (259c3f) 2026-07-02T07:11:03.000Z
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
Environment
- Claude Desktop 1.18286.0.0 (MSIX,
C:\Program Files\WindowsApps\Claude_1.18286.0.0_x64__pzs8sxrjxfjjc\app\Claude.exe) - Windows 10 x64
LocalCacherelocated to another drive via NTFS junction (shown above to be irrelevant to this bug)- Note:
--inspecton the packaged binary exposes no Node inspector target (fuse presumably burned), so I could not capture a JS-level profile; all evidence is syscall-level. ProcMon PML capture and call stacks of the transport-open events available on request.
Additional Observations
main.logcontent froze on 2026-06-04 while per-window logs (claude.ai-web.log,unknown-window.log,ssh.log,cowork_vm_node.log) carry current output — an update around that date appears to have moved live logging to per-window files while leaving the legacymain.logtransport (and its rotation checker) initialized. After deleting the oversized file,main.logis recreated and actively written again, so the legacy transport is still live.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗