Skip to content

bug: diagnostic report for concurrent web config rename EPERM on Windows #687

Description

@Bearmancer

Command Code Issue #686: EPERM During Concurrent Web Calls

Issue: #686
Generated: 2026-08-16
Command Code version: 1.26.0
Platform: Native Windows


1. Executive diagnosis

Command Code 1.26.0 marks web_search and web_fetch as concurrency-safe in the installed runtime. The same runtime contains a saveUserConfig() path that writes a uniquely named temporary file beside config.json, then immediately renames it over the destination.

Observed failures match that boundary exactly:

EPERM: operation not permitted, rename
'C:\Users\Lance\.commandcode\config.json.tmp-<id>'
->
'C:\Users\Lance\.commandcode\config.json'

Highest-confidence diagnosis:

Concurrent operations replace C:\Users\Lance\.commandcode\config.json without serialized destination access. Unique temporary names prevent temporary-file name collisions, but do not prevent competing renames to one destination. Windows intermittently rejects one replacement with EPERM.

The exact caller that invokes saveUserConfig() during web activity is not proven by available logs. That caller requires instrumentation.


2. User impact

  • Parallel research loses individual web results.
  • Search completeness becomes unreliable.
  • Retrying may succeed, hiding the race.
  • Web failures appear to be external network failures.
  • Official documentation fetches can fail locally.
  • No evidence currently shows configuration corruption or credential exposure.

3. Exact redacted EPERM evidence

All temporary-file identifiers are redacted. No credentials are included.

Session 007edd7e-d8ae-42d5-865e-cf86c64b36fb

Source:

C:\Users\Lance\.commandcode\projects\c-users-lance\007edd7e-d8ae-42d5-865e-cf86c64b36fb.jsonl

Timestamp: 2026-08-16T10:37:11Z

Error fetching https://commandcode.ai/docs/permissions: EPERM: operation not permitted, rename 'C:\Users\Lance\.commandcode\config.json.tmp-[REDACTED]' -> 'C:\Users\Lance\.commandcode\config.json'

Error fetching https://commandcode.ai/docs/error-codes: EPERM: operation not permitted, rename 'C:\Users\Lance\.commandcode\config.json.tmp-[REDACTED]' -> 'C:\Users\Lance\.commandcode\config.json'

Session d711ade7-1f5e-4fa4-9c9c-9f644f2a1c91

Source:

C:\Users\Lance\.commandcode\projects\c-users-lance\d711ade7-1f5e-4fa4-9c9c-9f644f2a1c91.jsonl

Timestamp: 2026-08-16T10:34:09Z

Error fetching https://www.usb.org/usb-typec: EPERM: operation not permitted, rename 'C:\Users\Lance\.commandcode\config.json.tmp-[REDACTED]' -> 'C:\Users\Lance\.commandcode\config.json'

Timestamp: 2026-08-16T10:34:20Z

Error searching the web: EPERM: operation not permitted, rename 'C:\Users\Lance\.commandcode\config.json.tmp-[REDACTED]' -> 'C:\Users\Lance\.commandcode\config.json'

Timestamp: 2026-08-16T10:34:35Z

Error fetching https://www.gsmarena.com/motorola_edge_70-review-2899p3.php: EPERM: operation not permitted, rename 'C:\Users\Lance\.commandcode\config.json.tmp-[REDACTED]' -> 'C:\Users\Lance\.commandcode\config.json'

Timestamp: 2026-08-16T10:37:11Z

Error searching the web: EPERM: operation not permitted, rename 'C:\Users\Lance\.commandcode\config.json.tmp-[REDACTED]' -> 'C:\Users\Lance\.commandcode\config.json'

Error fetching https://www.portronics.com/products/konnect-view-100w-pd-type-c-to-type-c-cable-2m: EPERM: operation not permitted, rename 'C:\Users\Lance\.commandcode\config.json.tmp-[REDACTED]' -> 'C:\Users\Lance\.commandcode\config.json'

Additional occurrence sets were recorded in sessions 7b290f2d, dbf8862e, and 55526254 on 2026-08-15.


4. Affected sessions and timeline

2026-08-15

  • 7b290f2d-e537-4d86-a29a-5272bc7fc1b1 — approximately 19:58–20:03 local time; temporary-mail searches and repository fetches.
  • dbf8862e-d43e-4f15-b683-3152fbde628a — approximately 15:06–15:20; YouTube, Azure, and pricing documentation.
  • 55526254-9604-47f7-85e0-05d2a412e908 — approximately 19:07–19:18; GitHub, crates.io, and Rust archiver research.
  • 40cdb32e-c8f5-42ce-9dcf-6d4b60624eae — approximately 10:13.
  • 68a2d223-ff4e-43e4-b65e-b161bfddb743 — approximately 10:12–10:21.

2026-08-16

  • d711ade7-1f5e-4fa4-9c9c-9f644f2a1c91 — approximately 10:34–10:37; USB-IF, GSM Arena, Motorola, and cable-product pages.
  • 007edd7e-d8ae-42d5-865e-cf86c64b36fb — approximately 10:37; official Command Code permissions and agents documentation.

The failure also reproduced during the diagnostic investigation while fetching official Command Code documentation. Other calls succeeded during the same periods, confirming intermittent behavior rather than universal web failure.


5. Reproduction procedure

  1. Run Command Code 1.26.0 on native Windows.
  2. Launch from PowerShell inside Windows Terminal.
  3. Request several independent web searches and fetches in one turn.
  4. Allow the agent to issue web calls concurrently.
  5. Observe different config.json.tmp-* paths targeting the same config.json.
  6. Observe intermittent EPERM failures.
  7. Repeat equivalent calls serially.
  8. Observe substantially improved reliability.
  9. Run:
cmdc config list --json
  1. Observe successful configuration reading after the web failure.

Missing controlled measurement

Current evidence does not contain a controlled N=parallel versus N=serial success-rate experiment. This should be added as an automated regression test rather than required from the reporter manually.


6. Controls already checked

File state

  • config.json exists.
  • config.json remains valid after failure.
  • File attribute is Archive.
  • File is not read-only.
  • Lance has FullControl.
  • Administrators have FullControl.
  • SYSTEM has FullControl.
  • cmdc config list --json succeeds.
  • No stale config.json.tmp-* files remain after failure.
  • No cmdc, node, or pwsh process holds the file during post-failure inspection.

Behavior

  • Parallel calls fail intermittently.
  • Serial calls are more reliable.
  • Unrelated URLs reproduce the same local rename error.
  • Failure is not tied to one remote website.
  • Failure is not explained by basic ACL denial.

Network scope

Affected destinations include GitHub, Command Code documentation, USB-IF, Motorola, GSM Arena, Azure, crates.io, and other unrelated services. The constant local destination path is the common factor.


7. System diagnostics

Command Code: 1.26.0
Operating system: Windows 10 Pro 22H2, x64
Windows version: 10.0.19045
Windows build: 19045
PowerShell: 7.6.5 Core
Node.js: v24.19.0
npm: 11.17.0
git: 2.55.0.windows.3
gh: 2.97.0
CPU: 12 logical processors
Physical memory: 16,456,253,440 bytes
Computer manufacturer: HP
Computer model: HP Laptop 17-cp0xxx
Terminal: Windows Terminal
Active shell: PowerShell 7.6.5
IDE: N/A
Command Code platform: Windows win32 x64
Command Code provider: command-code
Command Code model: gpt-5.6-luna
Command Code context window: 1,050,000
Authentication: verified

cmdc info reports cmd.exe for its shell field even though Command Code was launched from PowerShell inside Windows Terminal. This is a separate diagnostic-reporting issue, not the cause of EPERM.


8. Configuration diagnostics

Configuration path:

C:\Users\Lance\.commandcode\config.json

Checks:

Config ACL: Lance FullControl
Config read test: cmdc config list --json succeeded
Config read-only check: file not read-only
Stale temporary files after failure: none found
Running cmdc/node/pwsh process holding config: none found

No credentials or tokens are included.


9. Installed-bundle code analysis

Source and provenance

Installed source bundle:

C:\Users\Lance\AppData\Roaming\npm\node_modules\command-code\dist\cli.mjs

Package:

command-code 1.26.0

This is installed-bundle evidence, not public upstream source. The public GitHub main tree currently exposes documentation paths, not the runtime source tree.

9.1 Web concurrency declaration

The installed bundle's createWebSearchTool({transport}) returns:

readOnly: true
isReadOnly: () => true
isConcurrencySafe: () => true
shouldDefer: true

createWebFetchTool({transport, now}) returns the same declarations.

Meaning:

The scheduler is explicitly allowed to run web_search and web_fetch concurrently. This matches observed parallel execution.

9.2 User-config write path

Installed bundle saveUserConfig() logic is equivalent to:

async function saveUserConfig({runtime, path, config}) {
  const content = JSON.stringify(config, null, 2)
  const temp = `${path}.tmp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`
  await runtime.fs.write({path: temp, content, mode: 384})
  try {
    await runtime.fs.rename({from: temp, to: path})
  } catch (error) {
    await runtime.fs.rm({path: temp}).catch(() => {})
    throw error
  }
}

Observed correspondence:

  • Runtime destination: C:\Users\Lance\.commandcode\config.json
  • Runtime temp pattern: config.json.tmp-<timestamp>-<random>
  • Observed failure: EPERM from rename(temp, destination)

9.3 Concurrency gap

The installed function context contains no visible:

  • Process-wide mutex.
  • Write queue.
  • Inter-process lock.
  • Retry/backoff loop.
  • Compare-and-swap check.
  • Windows sharing-violation handling.

Unique temp names solve only temporary-name collision. They do not serialize competing renames to one destination.

Potential interleaving:

A writes config.json.tmp-A
B writes config.json.tmp-B
A renames tmp-A to config.json
B renames tmp-B to config.json
Windows or another process rejects one replacement with EPERM

9.4 Different general file-write behavior

Installed bundle writeFileSafely() also uses temp-write plus rename, but catches rename failure and falls back to direct destination write. saveUserConfig() cleans the temp file and rethrows instead.

Therefore:

  • General file writes may continue after rename failure.
  • User-config writes fail hard at rename failure.

9.5 Error classification gap

Installed bundle normalizeError() maps both EACCES and EPERM to generic PERMISSION.

This loses distinction between:

  • ACL denial.
  • Destination sharing violation.
  • Concurrent replacement.
  • Antivirus/indexer interference.
  • Another process holding the file.

The observed web error therefore hides the configuration-write cause behind a generic permission category.

9.6 Trace support gap

Installed bundle contains getTraceId(), getDisplayTraceId(), trackError(), and trace ID fields in telemetry/error records.

Observed gap:

Session records contain raw EPERM text but not the configuration-write operation, writer identity, lock owner, or stack. The configuration-write failure should include active trace ID and operation context.


10. Root-cause hypotheses

H1 — Highest confidence

Concurrent config writers replace one destination while web tools are marked concurrency-safe.

Evidence:

  • Exact temp naming pattern.
  • Repeated destination path.
  • Intermittent parallel failures.
  • Serial improvement.
  • Sufficient ACLs.

H2 — Possible

A separate Command Code process or lifecycle task writes configuration concurrently. Post-failure inspection cannot prove or disprove this because the competing process may release the file before inspection.

H3 — Possible

Windows antivirus, indexing, backup, or sync software briefly opens the destination or temporary file. Process Monitor capture during failure is needed.

H4 — Possible but unproven

Telemetry or another lifecycle event persists state during web calls. The bundle contains telemetry and trace code, but current evidence does not identify the saveUserConfig() caller during web execution.

H5 — Rejected as primary cause

Basic ACL denial. Configuration reads succeed, Lance has FullControl, failures are intermittent, and the same file remains usable after failure.


11. Required instrumentation

At saveUserConfig() entry

  • Operation name.
  • Caller.
  • Config path.
  • Process ID.
  • Thread/task identity.
  • Session ID.
  • Trace ID.
  • Config hash before write.
  • Persistence source.

Before rename

  • Temporary path.
  • Temporary size.
  • Destination existence.
  • Destination metadata.
  • Writer lock state.
  • Elapsed time.

On rename failure

  • Node error code.
  • errno.
  • Native Windows HRESULT/Win32 error.
  • Operation duration.
  • Retry count.
  • Destination hash before/after.
  • Temporary cleanup result.
  • Trace ID.
  • Caller.

At web-tool start/end

  • Tool name.
  • Call ID.
  • Session ID.
  • Trace ID.
  • Concurrency group.
  • Whether config mutation was requested.
  • Config hash before/after.

12. Required regression tests

  • Parallel saveUserConfig() calls to one destination on Windows.
  • Parallel web_search/web_fetch calls without config mutation.
  • Two Command Code processes writing one config path.
  • Rename EPERM/sharing-violation retry behavior.
  • Temporary cleanup after failed rename.
  • Configuration validity after concurrent failures.
  • Web result retry after successful configuration persistence.
  • Error reports configuration-write race rather than generic web failure.
  • Serial and parallel web calls produce equivalent results.
  • Scheduler concurrency safety includes adjacent lifecycle writes.

13. Requested fix

  1. Serialize all writes to config.json with a process-wide write queue or mutex.
  2. Add an inter-process lock if multiple Command Code processes can run concurrently.
  3. Avoid writes when read-only web calls produce no state change.
  4. Add bounded retry/backoff for Windows EPERM and sharing violations.
  5. Preserve and retry the original web call after configuration persistence succeeds.
  6. Classify sharing/race errors separately from ACL permission errors.
  7. Include configuration-write context and trace ID in tool errors.
  8. Add Windows concurrency regression tests.
  9. Correct cmdc info shell detection separately.

14. Workaround

Run independent web calls serially. Restarting Command Code may reduce recurrence temporarily.


15. Related issues checked


16. Privacy

No credentials, API keys, authentication tokens, or unrelated raw session content are included in this document.

Redacted evidence bundle:

https://gist.github.com/Bearmancer/9441c3c2e59adc3d0b7d6c8ad54aa44d

Full diagnostic document:

https://gist.github.com/Bearmancer/ec685865288b143700419c001f596153

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions