[BUG] Desktop (Win): oversized main.log triggers rotation-check loop that never issues the rename — ~8-9% CPU at idle; log lines doubled

Open 💬 1 comment Opened Jul 3, 2026 by nikitaivantsov

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:

  1. Trigger: main.log exceeds the 10 MiB rotation threshold (observed file: 10,487,371 bytes; threshold appears to be 10,485,760).
  2. Logic bug: the rotation code completes every preparatory step — stat shows file over threshold, probes main1.log/main2.log/main3.log for a free archive slot (all NAME NOT FOUND), opens main.log with 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 no SetRenameInformationFile, no SetDispositionInformationFile, 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.
  3. 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.
  4. Aggravator (related defect, same init path): the main.log file transport is registered twice — every log line is written twice, the process holds three open handles to main.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 SetRenameInformationFile or SetDispositionInformationFile.
  • Zero failing operations — every event in the loop returns SUCCESS (the main1/2/3.log NAME 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 LocalCache is 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

  1. Quit Claude fully (tray → Quit).
  2. Move the oversized main.log out of the logs folder → relaunch → CPU immediately drops to baseline.
  3. 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.log exceeds 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.log transport should be registered once; log lines should not be duplicated.

Error Messages/Logs

Steps to Reproduce

  1. Use Claude Desktop on Windows until main.log exceeds 10 MiB (accelerated 2× by the duplicate-write defect), or place any >10 MiB main.log into the logs directory.
  2. Launch the app. No interaction needed.
  3. Observe: main Claude.exe sustained ~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
  • LocalCache relocated to another drive via NTFS junction (shown above to be irrelevant to this bug)
  • Note: --inspect on 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.log content 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 legacy main.log transport (and its rotation checker) initialized. After deleting the oversized file, main.log is recreated and actively written again, so the legacy transport is still live.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗