Codex app freezes with no error when config.toml has duplicate tables

A malformed config.toml fails in one of two visible ways: the CLI prints 'Error loading config.toml:' with an absolute path, line and column, and refuses to start; the desktop app shows nothing useful — a blank window, a startup screen that never finishes, or a setup loop — while the real error sits in a log file under $CODEX_HOME/log. The most reported cause of the silent freeze is a duplicated TOML table, but a bad escape or a duplicate key can fail the same silent way.

Start here

Search config.toml for any table header that appears twice, and on the CLI read the path:line:column it prints.

What you see

You edited config.toml, and now the client fails in one of two visibly different ways.

  • On the CLI, the failure is loud: it prints Error loading config.toml: followed by the absolute path, line and column, then a parser message, and the CLI refuses to start. One reporter’s log read failed to reload config: C:\Users\<user>\.codex\config.toml:150:77: missing escaped value, expected b, e, f, n, r, `, ", x, u, `U“.
  • On the desktop app, the failure is silent: the window opens but stays on a loading screen, goes blank, or loops through setup with no clear error in the interface. The real error sits in a log file under the Codex log directory ($CODEX_HOME/log, which defaults to ~/.codex/log and contains files such as codex-tui.log). Reinstall, repair and reset do not help, because the broken user file survives.

The most reported cause of the silent freeze is a duplicated TOML table (most often an MCP server block added twice). But a malformed document can also fail this way without any duplicate.

What it usually means

TOML forbids defining the same table twice. This is not a Codex-specific rule; it is how the format works. A file like this is invalid:

[mcp_servers.example]
url = "https://example.invalid/mcp"
enabled = true

# The same table declared a second time - invalid TOML
[mcp_servers.example]
url = "https://example.invalid/mcp"
enabled = true

The second block does not merge with the first. The document has a duplicated key, and a parser is entitled to reject the whole file.

A duplicated key across layers can also break the app with no message: one reporter defined personality more than once (the snippet showed personality = "pragmatic") and got a completely blank window, with the log reading Failed to load config requirements and errorMessage="failed to read configuration layers: ..." (the ... is the reporter’s own elision, not literal text).

The reporter suspected that adding an MCP server through the interface may append a new block instead of updating the existing one, which would produce exactly this duplicate. That explanation is plausible but unconfirmed — treat it as a hint about where to look, not as an established cause.

Quick checks

  1. Did the problem start immediately after a config edit? If yes, this branch is worth checking first — it is cheap to confirm.
  2. On the CLI, read the printed path:line:column. The surfaced shape is Error loading config.toml: then <absolute path>:<line>:<column>: <parser message>. Two independent reporters on different platforms produced exactly this shape.
  3. On the desktop app, open the log, not the UI. The real error is in $CODEX_HOME/log (defaults to ~/.codex/log), not on screen. A loading screen that never finishes or a repeated setup loop is the app-side symptom.
  4. Search the file for repeated table headers. Look for any [section] or [section.subsection] header that appears twice.
  5. Is there a second config file in play? A project .codex/config.toml or a profile file can override or duplicate a key.

Fixes, by branch

If the CLI prints a parse error with a line and column

  1. Back up the file first. Copy config.toml somewhere safe before editing.
  2. Open the file at the printed path in a plain-text editor that shows line numbers, and go to the reported line and column.
  3. Fix the quoted cause. Common cases seen in reports:
    • An unclosed table — e.g. C:\Users\user\.codex\config.toml:136:46: unclosed table, expected ]“. One reporter’s root cause was a non-ASCII path whose bytes were decoded as GBK and re-encoded as UTF-8, consuming the closing quote; adding the missing ' back fixed it. The reporter explicitly declined to attribute the corruption to Codex.
    • A bad escape in a Windows path inside a TOML double-quoted string — e.g. missing escaped value, expected b, e, f, n, r, `, ", x, u, U``. In TOML, \d` is not a legal escape. The reporter’s broken line was a Windows path with unescaped backslashes. Two cheap workarounds: use forward slashes, or use TOML single-quoted (literal) strings, which take backslashes verbatim.
  4. Save, fully quit the client, and relaunch it. Quitting matters — a cached configuration can survive a simple window close.

If the app refuses to start because of a duplicate table

  1. Back up the file first. Copy config.toml somewhere safe before editing. You are about to change the file that controls how your client starts.
  2. Open the file in a plain-text editor that shows line numbers, so you can see where each block begins.
  3. Find every repeated header. Group blocks by header name and check whether any header appears twice.
  4. Merge the repeated blocks into one. Keep the keys you actually want. If the two copies disagree, decide which value is correct rather than keeping both.
  5. Save, fully quit the app, and relaunch it. Quitting matters — a cached configuration can survive a simple window close.
  6. Try starting a new chat. If the freeze was caused by the duplicate, this is where it clears.

If a duplicate key blanks the window

One reporter’s blank window came from personality defined more than once across layers. The workaround that worked was renaming %USERPROFILE%\.codex\config.toml to %USERPROFILE%\.codex\config.toml.disabled — a rename, not a delete, which disables the whole user config for that run and preserves the file for inspection. Back up first, and remember this disables every user-level setting, not one key.

If the duplicate keeps coming back

  • Check whether the same table is being written by two different things — for example a hand edit plus a change made through the interface.
  • After each change, re-read the file and confirm there is exactly one copy of each header before restarting.
  • Keep a known-good copy of the file so you can restore it in one step if a future edit goes wrong.

What not to do

  • Do not delete the entire Codex configuration directory. The reported failure is a single malformed document; the fix is to correct the document, and deleting everything destroys the rest of your setup.
  • Do not remove every MCP server at once. Narrow down which block is duplicated first, because otherwise you lose the information you need if a different server is involved.
  • Do not disable security features to work around a parse error. They are unrelated.
  • Do not run a config-validation command. No codex config validate or codex config check was found in any documentation opened, and codex exec --strict-config appeared only once in a report whose author then retracted it and is absent from the documented global flags. There is no documented way to validate a config file.
  • Do not delete the session store or log directory to clear a parse error; the fix is in config.toml.

How to tell it worked

The CLI starts and prints no config error, or the app starts, a new chat can be created, and a message can be sent. Because the desktop failure mode is silent, confirm it in the app itself (or in the log under $CODEX_HOME/log) rather than assuming the edit was enough.

If it is still failing

If the file is now valid TOML with one copy of each header and the app is still unresponsive, this guide does not apply. Revert to your backup, then look at the MCP startup path instead — a server that cannot start is a different failure with a different warning in the logs. If the CLI still prints a parse error after your fix, re-read the exact line and column it reports; the error is in that position.

Known limits of this guidance

  • Evidence level: reported. One detailed public report with a minimal reproduction of the duplicate-table freeze, plus separate reports of an unclosed table (#38500), a bad Windows-path escape (#37616), and a duplicate key that blanked the window (#40855).
  • The reporter’s explanation of how the duplicate appeared is a hypothesis, not a confirmed mechanism. #38500’s reporter explicitly declined to blame Codex for the corrupted entry.
  • The original report was on macOS with a specific app build; the surfaced-parse-error and duplicate-key reports are Windows app builds. Four of the five config-damage reports opened are Windows — do not assume the failure class is uniform across platforms.
  • The documented config-reference page contains no TOML parse-error text, no duplicate-key text and no validation command; the surfaced strings come from user reports, not documentation.
  • No literal duplicate-key or duplicate-table parser message was found. The duplicate case is described by its symptom (blank window, Failed to load config requirements); no parser string may be quoted for it.
  • --strict-config is undocumented and its one report was retracted; it is not a validation command. No fix version can be named — #40855 is closed with no stated resolution and the rest are open.

Sources

Each source lists what it is used to support. Sources are re-read on the review schedule, not continuously.

How this page is checked
Evidence level
Reported - based on public reports, not reproduced here
Last reviewed
2026-09-20
Content updated
2026-09-20
Full version scope
Reported on Codex App 26.303.1606 (806) on macOS, and on Windows app builds 26.803.5235.0, 26.808.x and 26.820.7780.0, among others opened. Other versions and platforms have not been documented as affected, and no fix version can be named.
Symptoms indexed
  • The app starts but a new chat cannot be sent
  • There is no error message anywhere in the interface
  • It started right after you edited config.toml
  • Removing the duplicate block and restarting fixes it immediately
  • On the CLI, a line such as 'Error loading config.toml: <path>:<line>:<column>: <parser message>' appears and the client will not start
  • On the desktop app, the window stays on a loading screen or loops setup with no on-screen error

Reviewer note

One detailed duplicate-table report plus separate reports of an unclosed table (#38500), a Windows backslash escape (#37616) and a duplicate key that blanked the window (#40855). The CLI-vs-desktop surfacing asymmetry is documented by those reports and by the documented log_dir. No reproduction was performed here; --strict-config is undocumented and retracted, and no validation command exists.