Codex wrote a double `else` block in JS - syntax hallucination.

Resolved 💬 2 comments Opened Nov 6, 2025 by jcs180 Closed Nov 11, 2025
💡 Likely answer: A maintainer (etraut-openai, contributor) responded on this thread — see the highlighted reply below.

What version of Codex is running?

0.46.0

What subscription do you have?

Plus

Which model were you using?

gpt-5-codex (medium)

What platform is your computer?

MacOS

What issue are you seeing?

Codex just produced some totally wrong code (double else block in JS):

} else {
              activateTab(tab);
            } else {
              activateTab(tab);
              tab.focus();
            }

What steps can reproduce the bug?

Uploaded thread: 019a54c7-55eb-7d80-8a9d-cbf020af9b20

What is the expected behavior?

To write valid JS.

Additional information

_No response_

View original on GitHub ↗

2 Comments

etraut-openai contributor · 9 months ago

Thanks for the bug report. We've shared the feedback with the team members who are responsible for training our codex models. We're tracking this feedback and similar reports so we can make the model more robust in future iterations.

If you see other model behavior that you'd like to report, please use the recently-added /feedback command in the CLI. That will provide us with additional details including logs and conversation text.

aquamarinz · 2 months ago

+1, reproduced on macOS — concrete numbers and a SQLite-level workaround below.

Environment: codex-cli 0.142.0-alpha.6 (Codex.app), macOS.

The rolling deletion on this table hides how much is actually written — file
size alone badly understates it. The cleanest probe is the AUTOINCREMENT
counter vs the live row count:

  • sqlite_sequence.seq for logs = 110,904,661 → that many rows INSERTed

over ~9.9 days ≈ 130 inserts/sec average (bursts far higher while
streaming).

  • Live COUNT(*) = 41,041 → ~99.96% already deleted. INSERT + rolling

DELETE = double the write traffic; the SSD wear already happened regardless
of the later deletion.

  • File had grown to 961,294,336 bytes (~917 MB), of which **87.9% (~805 MB)

were free pages** never reclaimed (no VACUUM).

  • By level: TRACE = 48% of rows / 61% of bytes. Top targets:

codex_otel.log_only, codex_otel.trace_safe,
codex_api::endpoint::responses_websocket (per-event streaming traces).

So on consumer SSDs this is real write amplification, exactly as described.

Workaround (until there's a config switch / retention cap) — stops the
writes at the DB layer without touching the binary:

-- the trace data is disposable; back up the schema if you like
CREATE TRIGGER block_logs_insert BEFORE INSERT ON logs
BEGIN SELECT RAISE(IGNORE); END;
PRAGMA wal_checkpoint(TRUNCATE);
VACUUM; -- reclaimed 824 MB here (917 MB -> 93 MB)

RAISE(IGNORE) silently drops the inserts (no error surfaced to codex;
sqlite_sequence then freezes, which doubles as proof it's working). Fully
reversible with DROP TRIGGER block_logs_insert.

Trade-offs worth flagging:

  • It disables the trace context that codex feedback / doctor reports attach —

fine if you don't use those.

  • A future migration that rebuilds the logs table will silently drop the

trigger and writes resume, so a small periodic check that re-arms it helps.

A built-in fix (env/config to disable or cap the SQLite trace sink + periodic
VACUUM) would be the real solution. Thanks!