Windows tool shell contains both Path and PATH, breaking Start-Process with redirected stdio

Open 💬 0 comments Opened Jun 10, 2026 by sosplease

Summary

Codex Desktop on Windows launches tool shells with both Path and PATH in the process environment. Windows environment variable lookup is case-insensitive, and this duplicate breaks PowerShell/.NET APIs that copy the environment into a case-insensitive dictionary.

Environment

  • OS: Windows
  • Codex Desktop package observed: OpenAI.Codex_26.608.1337.0_x64__2p2nqsd0c76g0
  • Workspace shell: Windows PowerShell

Reproduction

In a normal PowerShell session outside Codex:

[Environment]::GetEnvironmentVariables('Process').Keys | Where-Object { $_ -ieq 'PATH' }

Observed outside Codex:

Path

Inside a Codex tool shell, run the same command:

[Environment]::GetEnvironmentVariables('Process').Keys | Where-Object { $_ -ieq 'PATH' }

Observed inside Codex:

Path
PATH

The two values are identical except for Codex-added path entries.

Then attempt a normal background launch with redirected stdio:

$out = Join-Path (Get-Location) 'server.out.log'
$err = Join-Path (Get-Location) 'server.err.log'
Start-Process -FilePath node -ArgumentList 'server.mjs' -WorkingDirectory (Get-Location) -WindowStyle Hidden -RedirectStandardOutput $out -RedirectStandardError $err -PassThru

Observed error:

Start-Process : Item has already been added. Key in dictionary: 'Path'  Key being added: 'PATH'

Expected behavior

On Windows, Codex should normalize environment variable keys case-insensitively before launching tool shells/commands. It should preserve the canonical Windows Path key and update that key when prepending Codex paths, rather than creating a separate PATH key.

Why this matters

This prevents Codex from using normal PowerShell Start-Process patterns for local dev servers with redirected stdout/stderr. Foreground node server.mjs works, but normal detached process launching from Codex fails because of the duplicate environment key.

Suggested fix

Before spawning Windows shell/tool commands, normalize env keys case-insensitively. For the path variable specifically, keep one canonical key:

function normalizeWindowsEnv(env: Record<string, string>) {
  if (process.platform !== 'win32') return env;

  const output: Record<string, string> = {};
  const seen = new Map<string, string>();

  for (const [key, value] of Object.entries(env)) {
    const lower = key.toLowerCase();

    if (lower === 'path') {
      const canonical = seen.get('path') ?? 'Path';
      output[canonical] = value;
      seen.set('path', canonical);
      continue;
    }

    if (!seen.has(lower)) {
      seen.set(lower, key);
      output[key] = value;
    }
  }

  return output;
}

Then prepend Codex-specific path entries to the retained Path value instead of adding PATH.

View original on GitHub ↗