macOS: Persistent SQLite TRACE target=log churn remains after rust-v0.142.0

Open 💬 43 comments Opened Jun 23, 2026 by pwukun
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

After upgrading to rust-v0.142.0, I can still reproduce persistent SQLite log churn on macOS in ~/.codex/logs_2.sqlite.

This looks like a partial fix:

  • #29432 appears to have helped: codex_api::endpoint::responses_websocket is much lower than before.
  • However, #29457 does not appear to fully solve the persistent SQLite churn in this app build/runtime. The release note says noisy persistent log targets were filtered, and the PR says bridged target=log events should be excluded from the SQLite sink, but TRACE target=log is still the dominant persisted target here.

I also posted an earlier data point in the closed umbrella issue #28224 here:

https://github.com/openai/codex/issues/28224#issuecomment-4775086154

Opening a new issue because #28224 is closed and this is post-rust-v0.142.0 macOS data.

Environment

  • Platform: macOS 26.5.1, arm64
  • Codex app: 26.616.71553, build 4265
  • Embedded CLI: codex-cli 0.142.0
  • PATH CLI: codex-cli 0.142.0
  • App-server process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID/start at sample time: 7763, started Tue Jun 23 10:17:10 2026
  • RUST_LOG: empty
  • ~/.codex/config.toml: [analytics] enabled = false
  • SQLite trigger count during the sample: 0
  • logs_2.sqlite journal mode: wal

No local block_log_inserts trigger was present during this sample.

Files observed

At the start of the sample:

~/.codex/logs_2.sqlite      745,517,056 bytes
~/.codex/logs_2.sqlite-wal    4,437,272 bytes
~/.codex/logs_2.sqlite-shm       32,768 bytes

The active app-server process was holding the DB/WAL/SHM files open.

Read-only 60 second sample

Sample window:

2026-06-23 10:43:00 +0800 to 2026-06-23 10:44:00 +0800

SQLite metadata before/after:

trigger_count:        0 -> 0
row_count:       200589 -> 200589
max_id:       725810463 -> 725811933
sqlite_seq:   725810463 -> 725811933
max_ts:      1782182580 -> 1782182638

So the retained row count stayed flat, but sqlite_sequence / max_id advanced by 1,470 in about 60 seconds. This looks like continued insert-and-prune churn.

File mtimes also moved during the sample:

logs_2.sqlite mtime:     1782182580 -> 1782182613
logs_2.sqlite-wal mtime: 1782182580 -> 1782182638

The WAL size stayed stable at about 4.4 MB, so file size alone hides the ongoing write activity.

Recent persisted targets

Rows in the last 60 seconds:

TRACE log                                      989 rows, 526.8 KiB
TRACE codex_api::sse::responses                14 rows,  14.0 KiB
TRACE codex_app_server::outgoing_message        12 rows,   2.0 KiB
TRACE codex_mcp::connection_manager              6 rows,   4.9 KiB
DEBUG codex_core::stream_events_utils            3 rows,   3.3 KiB
INFO feedback_tags                               3 rows,   3.0 KiB
INFO codex_core::stream_events_utils             2 rows,   5.5 KiB
TRACE codex_api::endpoint::responses_websocket   1 row,   40.8 KiB
TRACE codex_core::session::turn                  1 row,    0.9 KiB

TRACE targets in the last 5 minutes:

log                                      989 rows, 526.8 KiB
codex_api::sse::responses                238 rows, 239.5 KiB
codex_mcp::connection_manager             18 rows,  13.8 KiB
codex_app_server::outgoing_message         12 rows,   2.0 KiB
codex_core::session::turn                   2 rows,   1.8 KiB
codex_api::endpoint::responses_websocket    2 rows,  80.0 KiB

Expected behavior

After rust-v0.142.0, Codex should not continuously persist high-frequency TRACE target=log rows into logs_2.sqlite by default, especially after #29457.

Actual behavior

Codex app-server continued to insert high-frequency TRACE target=log rows into the persistent SQLite log sink. The retained row count stayed flat, but max(id) / sqlite_sequence kept advancing and the DB/WAL mtimes kept moving, indicating ongoing insert-and-prune churn.

Privacy note

I am intentionally not pasting raw feedback_log_body contents because they may contain private conversation, local path, tool, or response data.

View original on GitHub ↗

43 Comments

github-actions[bot] contributor · 28 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #29463
  • #28224

Powered by Codex Action

zyfasos · 28 days ago

Additional macOS reproduction on the current Codex app build.

Environment:

  • Platform: macOS, Apple internal SSD (APPLE SSD AP0512Z), SMART status Verified
  • Codex app: 26.616.71553, build 4265
  • Embedded CLI: codex-cli 0.142.0
  • App-server process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • Active app-server PID during sample: 34793
  • RUST_LOG=info was set via launchctl getenv RUST_LOG, but persisted SQLite rows still included TRACE and DEBUG.
  • No SQLite trigger or DB mutation was applied during this sample; the checks below were read-only.

Files observed:

~/.codex/logs_2.sqlite      302,129,152 bytes (~288M)
~/.codex/logs_2.sqlite-wal   13,113,992 bytes (~13M)
~/.codex/logs_2.sqlite-shm       32,768 bytes

lsof showed the active Codex app-server process holding open handles to the DB, WAL, and SHM files.

60-second quiet sample:

Sample start: 2026-06-23 10:40:06 CST
Sample end:   2026-06-23 10:41:07 CST
max(id):      19457302 -> 19458968  (+1666)
count(*):     29226 -> 29235        (+9)
max(ts):      1782182405 -> 1782182465
WAL mtime:    kept advancing throughout the sample

This again suggests insert-and-prune churn: retained row count barely changed, but max(id) advanced by 1,666 in about a minute.

Rows visible in that sample window included:

TRACE log                                 870 rows, 473846 estimated bytes
TRACE codex_app_server::message_processor 13 rows
TRACE codex_api::sse::responses           11 rows
TRACE hyper_util::client::legacy::pool    11 rows
TRACE codex_app_server::outgoing_message   9 rows
TRACE codex_mcp::connection_manager        8 rows

Total visible TRACE rows in the sample window: 940.

The latest TRACE target=log samples were websocket/tungstenite noise, including:

WouldBlock
tokio-tungstenite ... Read.with_context read -> poll_read
WebSocketStream.with_context
Stream.poll_next
Received message ...
decompressing ... bytes in final frame
received frame <FRAME> ...

Current visible level distribution at collection time:

TRACE  15498 rows  53.03%
INFO   12331 rows  42.19%
DEBUG   1321 rows   4.52%
WARN      71 rows
ERROR      5 rows

Impact: this creates sustained writes to the persistent SQLite log sink during normal Codex app use. RUST_LOG=info did not stop these persisted TRACE rows, so the user-level mitigation does not appear to work for this path.

I have a private evidence package with raw command output, SQLite read-only queries, file metadata, hashes, and the 60-second WAL/SQLite sample. I am not attaching raw feedback_log_body contents publicly because they may include local paths, conversation IDs, command fragments, or response data.

vadxq · 28 days ago

Please fix this as soon as possible! This issue is widespread and serious. Thank you.

lock-down · 28 days ago

+1 Please fix this as soon as possible! This issue is widespread and serious. Thank you.

nomideus · 27 days ago

Additional current-build datapoint from macOS Desktop 26.616.71553 / build 4265, bundled/global codex-cli 0.142.0.

During active Desktop use, I temporarily removed a local SQLite mitigation trigger, recorded max(id)=707460512, waited 15 seconds, then restored the trigger. New retained rows over that window:

total_new_rows=1196
log|TRACE|934
codex_api::sse::responses|TRACE|138
codex_app_server::outgoing_message|TRACE|37
codex_mcp::connection_manager|TRACE|20
codex_config::loader::macos|DEBUG|8
codex_core::stream_events_utils|DEBUG|7
feedback_tags|INFO|7
codex_models_manager::cache|INFO|6
codex_models_manager::manager|INFO|5
codex_app_server::message_processor|TRACE|4
codex_config::loader::layer_io|DEBUG|4
codex_core::session::turn|TRACE|4
codex_core::stream_events_utils|INFO|4
codex_api::endpoint::responses_websocket|TRACE|3
codex_core::spawn|TRACE|3

Rows matching the previously noisy targets (log, codex_otel.log_only, codex_otel.trace_safe, codex_api::endpoint::responses_websocket, codex_api::sse::responses) were 1075 in the same 15-second window.

This is another confirmation that the current Desktop app-server path is still persisting high-volume TRACE target=log rows on the shipped 0.142.0 build. The local mitigation trigger was restored after the measurement.

MKA930 · 27 days ago

+1 OMG🤯

RonZhu · 27 days ago

Additional macOS data point from another machine: I can still reproduce persistent SQLite TRACE churn after restarting Codex Desktop and after manually compacting the log DB.

Environment

  • Platform: macOS arm64
  • Codex Desktop: 26.616.71553, build 4265
  • Embedded CLI: codex-cli 0.142.0
  • PATH CLI: codex-cli 0.142.0
  • Active Desktop app-server process:
  • /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • A separate older stdio app-server process was also present, but recent rows were dominated by the restarted Desktop app-server process.
  • RUST_LOG observed in the process environment: warn
  • ~/.codex/logs_2.sqlite journal mode observed earlier: wal

I am not attaching or pasting raw feedback_log_body rows because they can contain private conversation/tool/local-path details.

Before manual cleanup

Before compacting, the local log files were:

~/.codex/logs_2.sqlite       703M
~/.codex/logs_2.sqlite-wal   128M
~/.codex/logs_2.sqlite-shm   256K

The table showed high churn/free space:

rows:           143001
page_count:     179883
freelist_count: 133819
page_size:      4096

A 30 second sample after restarting Codex Desktop showed continued insert-and-prune activity:

max(id) delta: about +1414 in 30s
approx rate:   45-50 inserted ids/sec

Recent 2 minute target distribution during that sample was still dominated by TRACE rows:

TRACE log                                      1071 rows
TRACE codex_mcp::connection_manager             55 rows
TRACE codex_api::sse::responses                 51 rows
TRACE codex_app_server::outgoing_message        51 rows
TRACE codex_api::endpoint::responses_websocket   4 rows, about 2.17 MiB estimated

After manual cleanup / compaction

I then retained only a small recent window of diagnostic rows and ran checkpoint/VACUUM. Integrity check returned ok, and the files were reduced to:

15:53:24 local
logs_2.sqlite       1.8M
logs_2.sqlite-wal     0B
logs_2.sqlite-shm   256K
rows:               1855

However, without changing anything else, Codex Desktop quickly started growing the files again. About 80 seconds later:

15:54:44 local
logs_2.sqlite       38M
logs_2.sqlite-wal   37M
logs_2.sqlite-shm   256K
rows:               2061
max(id):            243430233

Rows retained in the last 5 minutes at that point:

TRACE log                                      1054 rows, 0.18 MiB estimated
TRACE codex_api::sse::responses                621 rows, 0.60 MiB estimated
TRACE codex_mcp::connection_manager            187 rows, 0.19 MiB estimated
TRACE codex_app_server::outgoing_message        48 rows
DEBUG codex_core::stream_events_utils           45 rows
TRACE codex_api::endpoint::responses_websocket   8 rows, 0.57 MiB estimated

Expected

After rust-v0.142.0 / #29432 / #29457, the persistent SQLite sink should not continue high-frequency insert-and-prune churn dominated by TRACE target=log and related websocket/SSE targets during normal Desktop use.

Actual

Even after restart and after compacting the database down to a tiny valid state, the active Desktop app-server began writing again immediately. The on-disk DB/WAL grew from about 1.8M + 0B to about 38M + 37M within roughly 80 seconds, and the retained recent rows were still dominated by TRACE targets.

This makes the current behavior look like an incomplete fix or a remaining Desktop-app persistent-log sink path that still persists noisy TRACE rows.

mdbecker · 27 days ago

I’m seeing what looks like the same underlying SQLite churn pattern on macOS, though my setup differs slightly: I have not specifically disabled analytics/plugins, and the running process is codex app-server --analytics-default-enabled.

I posted the fuller diagnostic here: https://github.com/openai/codex/issues/29612#issuecomment-4780728496

Summary of my repro:

Codex Desktop: 26.616.71553 • Released Jun 22, 2026
Bundled CLI: codex-cli 0.142.0
Platform: macOS 15.3, Darwin 24.3.0, arm64
Launch method: macOS GUI / Spotlight
Running process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
Actual process env includes: RUST_LOG=warn

Over a 5-minute idle sample, with Codex Desktop open in the background but not actively used:

new_insert_ids=2975
retained_row_delta=0
insert_ids_per_sec=9.92

The DB was healthy and compacted beforehand, so this did not appear to be leftover pre-fix bloat:

quick_check=ok
integrity_check=ok
journal_mode=wal
freelist_count=115
logs_2.sqlite≈63M
logs_2.sqlite-wal≈4.1M

The exact sampled ID window showed retained rows dominated by TRACE target=log:

TRACE log                                998 rows
TRACE hyper_util::client::legacy::pool     2 rows

All retained rows from that sampled window belonged to the same app-server process.

So this looks like the same post-0.142.0 behavior: file size may remain bounded, but the app-server still continuously inserts and prunes persistent SQLite log rows while idle, mostly TRACE target=log, despite RUST_LOG=warn.

nicksenround1 · 27 days ago

Additional macOS datapoint after cleanup/compaction, from another affected machine.

I can still reproduce the post-0.142.0 insert-and-prune churn after fully compacting the log DB. The historical bloat was cleaned up successfully, but the current app-server continues to persist TRACE target=log rows.

Environment

Platform: macOS arm64
Codex Desktop: 26.616.71553
CFBundleVersion: 4265
CLI: codex-cli 0.142.0
Running process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
App-server PID/start: 9920, Wed Jun 24 10:19:03 2026 AEST
Process env: RUST_LOG=warn
Active DB: ~/.codex/logs_2.sqlite

The active app-server process was holding open handles to logs_2.sqlite, logs_2.sqlite-wal, and logs_2.sqlite-shm.

Before cleanup

Before manually clearing/compacting the DB, the files had grown to:

~/.codex/logs_2.sqlite      811M
~/.codex/logs_2.sqlite-wal   68M
~/.codex/logs_2.sqlite-shm  160K

SQLite stats at that point showed this was mostly free pages from churn:

rows:           24495
page_size:       4096
page_count:    207595
freelist_count:195037
estimated_payload_mb: 26.66

After DELETE FROM logs, resetting the sequence, and VACUUM, the DB compacted successfully:

~/.codex/logs_2.sqlite      5.3M
~/.codex/logs_2.sqlite-wal  4.0M-4.3M
~/.codex/logs_2.sqlite-shm   32K

Repro after cleanup / restart

Immediately after cleanup and restart, rows began accumulating again, dominated by TRACE target=log:

rows: 1062
seq: 4027
TRACE log: 978 rows

A 20-second sample shortly after restart showed much higher active churn:

window_start=2026-06-24 10:19:48 AEST
window_end=2026-06-24 10:20:08 AEST
delta_seq=15923
rows_per_sec=796.1
delta_count=4

Top retained rows from that ID window:

TRACE log                                      932 rows, 0.176 MiB
TRACE codex_app_server::outgoing_message       39 rows
TRACE hyper_util::client::legacy::pool          7 rows
TRACE hyper_util::client::legacy::client        6 rows
TRACE codex_api::sse::responses                 2 rows

A later quieter 30-second sample still showed the same insert-and-prune pattern with file sizes bounded:

window_start=2026-06-24 10:23:52 AEST
window_end=2026-06-24 10:24:22 AEST
start_seq=67982
end_seq=68515
delta_seq=533
rows_per_sec=17.8
start_count=2049
end_count=2049
delta_count=0
start_db=5541888
end_db=5541888
delta_db=0
start_wal=4486712
end_wal=4486712
delta_wal=0

Top retained rows from that sampled ID window:

TRACE log                                      475 rows, 0.212 MiB
TRACE codex_app_server::outgoing_message       12 rows
TRACE hyper_util::client::legacy::pool         10 rows
TRACE hyper_util::client::legacy::client        6 rows
TRACE codex_api::sse::responses                 4 rows
DEBUG hyper_util::client::legacy::connect::http 4 rows

I am intentionally not pasting raw feedback_log_body values because they may contain private local paths, conversation, tool, or response data.

User-visible impact

Before cleanup, while several Codex tasks were open at the same time, I observed frequent Codex restarts and UI lag. Cleaning/VACUUM reduced the historical DB size from ~811M to ~5.3M, but the high-frequency TRACE target=log insert/prune behavior is still present on the current Desktop app-server.

So the remaining issue seems to be: 0.142.0 reduces/bounds some file-size growth, but the shipped macOS Desktop app-server still persists high-frequency TRACE target=log rows and continues SQLite churn even with RUST_LOG=warn.

zyfasos · 27 days ago

Additional datapoint after updating to the newer macOS app build 26.616.81150 / build 4306.

Environment:

  • Codex app: 26.616.81150, build 4306
  • Embedded CLI: codex-cli 0.142.0
  • Active app-server process started after update: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID during sample: 88553, started Wed Jun 24 09:20:21 2026
  • A local SQLite mitigation trigger existed before the test, so I temporarily removed it for a controlled 30-second sample, then restored it immediately afterward.

Controlled sample with the trigger disabled:

Sample window: 2026-06-24 09:22:34 CST to 09:23:05 CST
max(id):       19975524 -> 19975884 (+360)
count(*):      33614 -> 33965 (+351)
WAL size:      0 -> 1,030,032 bytes during the sample

Rows visible in the sample window:

TRACE log                                      441 rows, 271850 estimated bytes
TRACE codex_app_server::outgoing_message        4 rows
TRACE codex_mcp::connection_manager             4 rows
TRACE codex_api::endpoint::responses_websocket  1 row
TRACE codex_api::sse::responses                 1 row
TRACE codex_core::session::turn                 1 row
TRACE hyper_util::client::legacy::pool          1 row

Total TRACE rows in the 30-second window: 453.

The latest TRACE target=log rows are still websocket/tungstenite noise, including WouldBlock, tokio-tungstenite, WebSocketStream.with_context, Stream.poll_next, Received message, decompression, and <FRAME> parsing lines.

So this still reproduces on app build 4306; it does not appear fully fixed by this build.

Don-Quijote224 · 26 days ago

现在macos的codex桌面端更新到了26.622.11653,还有这个问题吗

almostlover-hao · 26 days ago

Additional macOS data point from Codex Desktop showing that the issue still reproduces on my machine, and that sqlite_home is currently the only effective local mitigation I found.

Environment

  • Platform: macOS, Apple SSD (diskutil: SMART Status Verified, TRIM supported)
  • Codex Desktop app-server command:
  • /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • Codex app version exposed in local config/env:
  • BROWSER_USE_CODEX_APP_VERSION=26.616.81150
  • Embedded CLI:
  • codex-cli 0.142.0
  • SQLite DBs involved:
  • ~/.codex/logs_2.sqlite
  • ~/.codex/logs_2.sqlite-wal
  • ~/.codex/state_5.sqlite-wal

Config tried

~/.codex/config.toml included:

[analytics]
enabled = false

[otel]
log_user_prompt = false
exporter = "none"
trace_exporter = "none"
metrics_exporter = "none"

The restarted app-server process also inherited:

RUST_LOG=warn

Confirmed via:

ps eww -p <app-server-pid> -o command= | tr ' ' '\n' | rg '^(RUST_LOG|CODEX|OTEL|RUST)='

Observed behavior before mitigation

After restarting Codex Desktop with the config above, a 60-second proc_pid_rusage sample still showed:

Codex-related processes total: 17.594 MB written / 60s
app-server alone:              17.082 MB written / 60s

The new app-server process had already accumulated substantial writes shortly after restart:

app-server start_written_mb=167.871

In an earlier active diagnostic window, app-server lifetime written bytes reached about:

app-server end_written_mb ~= 1373 MB

Recent rows in logs_2.sqlite still included persisted TRACE records despite RUST_LOG=warn:

TRACE  2957 rows  1.65 MB
DEBUG    95 rows  0.25 MB
INFO     84 rows  0.07 MB
WARN     13 rows  0.01 MB

Largest recent targets included:

codex_api::sse::responses                 TRACE
codex_api::endpoint::responses_websocket  TRACE
log                                       TRACE
codex_app_server::outgoing_message        TRACE
codex_mcp::connection_manager             TRACE

This confirms the SQLite feedback/log sink is still persisting TRACE-level data even when the process environment has RUST_LOG=warn and analytics/OTel exporters are disabled.

Why file size alone hides the issue

The retained DB size was not enough to estimate real write volume. The file stayed bounded while logs_2.sqlite-wal and SQLite insert/prune churn continued. This matches the pattern described in this issue: current file size can look moderate while SSD writes continue due to insert, WAL write, prune, checkpoint, and rewrite activity.

Local mitigation tested

I moved only Codex's SQLite-backed runtime state to a RAM disk:

sqlite_home = "/Volumes/CodexSQLiteRAM"

After restarting Codex Desktop, lsof confirmed these were all on the RAM disk:

/Volumes/CodexSQLiteRAM/logs_2.sqlite
/Volumes/CodexSQLiteRAM/logs_2.sqlite-wal
/Volumes/CodexSQLiteRAM/state_5.sqlite-wal
/Volumes/CodexSQLiteRAM/memories_1.sqlite-wal
/Volumes/CodexSQLiteRAM/goals_1.sqlite-wal

A follow-up 60-second sample still showed process-level writes:

Codex-related processes total: 8.230 MB written / 60s
app-server alone:              7.191 MB written / 60s

But visible internal SSD growth for the Codex SQLite files dropped to zero because the SQLite writes were on the RAM disk:

RAM_SQLITE_FILE_GROWTH_MB       0.118
SSD_OLD_SQLITE_FILE_GROWTH_MB   0.000
SSD_APP_LOG_FILE_GROWTH_MB      0.000
SSD_SESSION_FILE_GROWTH_MB      0.002

A broader 30-second scan of likely Codex internal-SSD paths showed only tiny non-SQLite growth:

~/.codex                                      0.000 MB
~/Library/Application Support/Codex           0.007 MB
~/Library/Caches/com.openai.codex             0.000 MB
~/Library/HTTPStorages/com.openai.codex       0.000 MB
~/Library/Logs/com.openai.codex               0.000 MB
TOTAL_BROAD_FILE_GROWTH_MB                    0.007 MB / 30s

So sqlite_home to RAM disk mitigates SSD wear, but it does not fix the root cause. It only moves the high-frequency SQLite WAL writes away from the internal SSD.

Expected fix

Please make the persistent SQLite log sink honor the same filtering as RUST_LOG / runtime log level, or provide a documented config option to disable persistent SQLite feedback logs or cap them aggressively. With RUST_LOG=warn, [analytics].enabled=false, and all [otel] exporters set to none, TRACE websocket/SSE/internal target=log records should not continue to be persisted to logs_2.sqlite during normal desktop usage.

Privacy note

I am not attaching the SQLite DB or raw feedback_log_body rows because they may contain private local paths, tool output, and conversation/session details.

RonZhu · 26 days ago

Follow-up after the question about macOS Desktop 26.622.11653:

I checked the affected macOS machine again today. This machine has not yet updated to 26.622.11653, so I cannot confirm whether that newer build fixes the issue.

Current local version on this machine:

Codex Desktop: 26.616.81150
CFBundleVersion: 4306
Embedded CLI: codex-cli 0.142.0
PATH CLI: codex-cli 0.142.0
Active Desktop app-server:
/Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled

On this 26.616.81150 / build 4306 install, the issue is still reproducible.

Before the latest sample, the log files had already grown again after the previous cleanup/compaction:

~/.codex/logs_2.sqlite       129M
~/.codex/logs_2.sqlite-wal   128M
~/.codex/logs_2.sqlite-shm   256K
integrity_check: ok
rows: 26794

A read-only ~30 second sample showed continued insert/prune churn:

max(id): 249441161 -> 249443723
max(id) delta: +2562
approx rate: ~85 inserted ids/sec
row count stayed roughly flat around 26.8k rows

Recent 5 minute target distribution was still dominated by TRACE rows:

TRACE log                                      959 rows, 0.27 MiB estimated
TRACE codex_api::sse::responses                549 rows, 0.35 MiB estimated
TRACE codex_mcp::connection_manager            242 rows, 0.23 MiB estimated
TRACE codex_app_server::outgoing_message        26 rows
TRACE hyper_util::client::legacy::pool          26 rows
TRACE hyper_util::client::legacy::client        21 rows
TRACE codex_api::endpoint::responses_websocket  11 rows, 2.83 MiB estimated

Recent rows were dominated by the active Desktop app-server process:

pid:20390 ... TRACE 1777 rows in the recent window

So my current data point is:

  • 26.616.81150 / build 4306: still reproduces.
  • 26.622.11653: not available on this machine yet, so I cannot confirm either way.

I am still not pasting raw feedback_log_body contents because they may contain private conversation/tool/local-path details.

denispol · 25 days ago

Confirming this on codex-cli 0.142.2, pinned to source tag rust-v0.142.2 (390b0d25). It's platform-independent (same as the Windows reports #29799/#29463 and macOS #29532); I just hit it on macOS where the OS flags excessive disk writes and, on a busy volume, the continuous WAL I/O stalled the host. It is disk I/O, not memory (process footprint ~130 MB).

Root cause, verbatim at the tag:

  • state/src/log_db.rs:53-59 — persisted sink hardcoded to LevelFilter::TRACE; RUST_LOG only drives the stderr layer (why RUST_LOG=warn has no effect, #29463).
  • state/src/runtime/logs.rs — a window-function DELETE runs inside every insert txn; caps LOG_PARTITION_SIZE_LIMIT_BYTES = 10 MiB, LOG_PARTITION_ROW_LIMIT = 1000 (runtime.rs:97-98).
  • state/src/runtime.rs:362-370 — WAL mode with no wal_autocheckpoint/journal_size_limit; wal_checkpoint(PASSIVE) only at startup (runtime/logs.rs:296-310) → unbounded WAL (#28997).
  • app-server/src/lib.rs:665-668 / tui/src/lib.rs:1242-1245 — sink started unconditionally; no config/env/flag to disable or lower it.

Cross-platform fix that fits the existing design: default the persisted sink to INFO with an env/config.toml override (mirroring how RUST_LOG drives the stderr layer) and a [log] persist = false off-switch; batch inserts into one txn per N ms/rows; move the prune off the insert path to a periodic task; and set wal_autocheckpoint + periodic wal_checkpoint(TRUNCATE) to bound the WAL. Ideally, keep recent logs in a bounded in-memory ring buffer and only materialize to SQLite when /feedback is invoked, eliminating steady-state disk writes.

denispol · 25 days ago

Follow-up to my analysis above: prepared a fix (configurable level w/ INFO default, off-switch, bounded WAL). Reference branch: https://github.com/denispol/codex/pull/1

zyfasos · 25 days ago

Additional macOS datapoint after updating to Codex app 26.623.31443 / build 4441.

Environment:

  • Codex app: 26.623.31443, build 4441
  • Embedded CLI: codex-cli 0.142.2
  • Active app-server process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID during sample: 18892, started Fri Jun 26 10:23:37 2026
  • RUST_LOG=info
  • A local SQLite mitigation trigger existed before the test, so I temporarily removed it for a controlled 30-second sample, then restored it immediately afterward and truncated the WAL again.

Controlled sample with the trigger disabled:

Sample window: 2026-06-26 10:27:03 CST to 10:27:33 CST
max(id):       19992963 -> 19995055 (+2092)
count(*):      34761 -> 35499 (+738)
WAL size:      0 -> 4,383,712 bytes during the sample

Rows visible in the sample window:

TRACE log                                      927 rows, 766302 estimated bytes
TRACE codex_api::sse::responses                22 rows
TRACE codex_app_server::outgoing_message       21 rows
DEBUG codex_core::stream_events_utils          18 rows
TRACE hyper_util::client::legacy::pool         17 rows
TRACE codex_mcp::connection_manager            16 rows
TRACE hyper_util::client::legacy::client       12 rows
DEBUG hyper_util::client::legacy::connect::http 10 rows
DEBUG log                                      10 rows
TRACE codex_api::endpoint::responses_websocket  4 rows

Total rows in the 30-second window:

TRACE 1028
DEBUG   46

This still reproduces on 26.623.31443 / build 4441 / codex-cli 0.142.2. The persisted TRACE/DEBUG path still appears to bypass RUST_LOG=info. The latest retained TRACE/DEBUG rows in the sample were network/proxy/client/poller/platform-detection noise, plus app-server/SSE/outgoing-message entries.

After the sample, I restored the local block_trace_debug_logs mitigation trigger and ran wal_checkpoint(TRUNCATE); the WAL returned to 0 bytes.

zyfasos · 24 days ago

Additional macOS datapoint after updating to Codex app 26.623.31921 / build 4452.

Environment:

  • Codex app: 26.623.31921, build 4452
  • Embedded CLI: codex-cli 0.142.2
  • Active app-server process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID during sample: 51634, started Fri Jun 26 14:05:49 2026
  • RUST_LOG=info
  • A local SQLite mitigation trigger existed before the test, so I temporarily removed it for a controlled 30-second sample, then restored it immediately afterward and truncated the WAL again.

Controlled sample with the trigger disabled:

Sample window: 2026-06-26 14:08:03 CST to 14:08:34 CST
max(id):       19997018 -> 19997370 (+352)
count(*):      36177 -> 36529 (+352)
WAL size:      0 -> 1,355,512 bytes during the sample

Rows visible in the sample window:

TRACE log                                 349 rows, 119071 estimated bytes
TRACE codex_app_server::outgoing_message   1 row
TRACE hyper_util::client::legacy::pool      1 row
INFO codex_core::stream_events_utils        1 row
INFO feedback_tags                          1 row

Total TRACE rows in the 30-second window: 351.

This still reproduces on 26.623.31921 / build 4452 / codex-cli 0.142.2, though this particular sample was lower volume than my previous 26.623.31443 / build 4441 sample. The latest retained TRACE target=log rows are still websocket/tungstenite frame noise including WouldBlock, WebSocketStream.with_context, Stream.poll_next, Received message, and <FRAME> parsing lines.

After the sample, I restored the local block_trace_debug_logs mitigation trigger and ran wal_checkpoint(TRUNCATE); the WAL returned to 0 bytes.

RonZhu · 24 days ago

Follow-up datapoint on the latest macOS app build I currently have installed.

Environment:

  • Codex app: 26.623.31921, build 4452
  • Embedded CLI: codex-cli 0.142.2
  • PATH CLI: codex-cli 0.142.2
  • Active app-server process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID during sample: 75427, started Fri Jun 26 14:15:39 2026
  • Process env: RUST_LOG=warn

Important note: I did not disable my local SQLite mitigation for this check. Two local triggers are currently installed:

  • sample_log_inserts: ignores inserts when the latest retained row is newer than NEW.ts - 10, effectively retaining at most about one row every 10 seconds.
  • trim_sampled_logs: keeps only the newest 500 retained rows.

With those triggers left enabled, the persisted rows still show that the source is continuously producing TRACE records after the update:

level distribution in retained rows:
TRACE 500 rows
retained time range: 2026-06-26 13:00:58 to 2026-06-26 14:24:22

The latest retained rows from the active app-server process continued at the mitigation cadence, about one retained row every 10 seconds:

14:22:12 TRACE hyper_util::client::legacy::pool
14:22:22 TRACE log
14:22:32 TRACE hyper_util::client::legacy::pool
14:22:42 TRACE log
14:22:52 TRACE log
14:23:02 TRACE log
14:23:12 TRACE log
14:23:22 TRACE log
14:23:32 TRACE log
14:23:42 TRACE log
14:23:52 TRACE log
14:24:02 TRACE log

The TRACE target=log entries are still websocket/tungstenite noise such as WebSocketStream.with_context and Stream.poll_next.

Current file sizes at the end of the check:

~/.codex/logs_2.sqlite      274432 bytes
~/.codex/logs_2.sqlite-wal  4161232 bytes  (mtime kept advancing during the check)
~/.codex/logs_2.sqlite-shm   32768 bytes

So the local trigger mitigation is keeping disk growth bounded on this machine, but the root issue still appears present on 26.623.31921 / build 4452 / codex-cli 0.142.2: the persistent SQLite sink is still receiving/storing TRACE-level records even with RUST_LOG=warn. The mitigation reduces retained/committed rows; it does not prove the upstream source has stopped emitting TRACE logs.

XiaDao · 24 days ago

Additional macOS datapoint on Codex app 26.623.31921 / build 4452.

Environment:

  • macOS
  • Codex app: 26.623.31921, build 4452
  • Embedded CLI: codex-cli 0.142.2
  • PATH CLI: codex-cli 0.142.2
  • Active app-server process:

/Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled

  • App-server PID during the sample: 18323
  • No local SQLite mitigation trigger is currently installed (sqlite_master trigger count: 0)

Watchdog sample:

Sample window: 2026-06-26 12:04:32Z to 12:11:32Z
Duration:      ~420 seconds
Samples:       84

Codex process bytes written:   2.68 GB
System disk write delta:       3.28 GB
Codex share of system writes:  ~82%
Average Codex write rate:      ~383 MB/min
Peak Codex write rate:         ~2387 MB/min at 12:06:02Z
Average CPU during window:     ~0.52%
High-write low-CPU samples:    40
Critical write samples:        27

Main writer attribution from the watchdog report:

Primary writer:
  codex pid 18323
  /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled

Latest-sample write delta:
  codex pid 18323: ~75.4 MB
  Codex app/renderer/service child processes: near zero or much smaller

The report also observed that the monitored hot files did not grow during the window:

~/.codex/logs_2.sqlite      size ~335 MB, delta +0 KB
~/.codex/logs_2.sqlite-wal  size ~35 MB,  delta +0 KB
~/.codex/logs_2.sqlite-shm  size ~98 KB,  delta +0 KB

This looks consistent with SQLite/WAL insert-prune/checkpoint or page-reuse churn: high process-level writes without corresponding file-size growth.

Current logs_2.sqlite state after the report:

row_count: 62943
max(id):   289747108
journal:   wal

Largest retained log-body targets currently visible:

TRACE codex_api::endpoint::responses_websocket  4042 rows, 53.89 MiB body, max row ~6.5 MB
TRACE codex_client::transport                    260 rows,  9.75 MiB body, max row ~8.55 MB
TRACE codex_api::sse::responses                  9343 rows,  8.55 MiB body
INFO  codex_otel.log_only                        4023 rows,  7.86 MiB body
INFO  codex_otel.trace_safe                      4005 rows,  7.48 MiB body
TRACE log                                        19264 rows, 5.77 MiB body

This still appears to be dominated by the desktop app-server persistent SQLite log path after the 0.142.x fixes. The watchdog report is useful because it correlates app-server process writes with system disk writes over a fixed window, not just retained SQLite row counts.

Could you confirm whether the intended fix is only to reduce retained rows/targets, or whether the persistent SQLite log sink is also expected to stop generating this level of WAL / insert-prune write amplification? A supported temporary config/env switch to disable or lower the persisted SQLite log sink would also help avoid local trigger workarounds.

XiaDao · 24 days ago

Follow-up CLI comparison after fully quitting the desktop app-server.

Procedure:

  • Quit Codex.app.
  • Verified no codex app-server process was running.
  • Captured logs_2.sqlite baseline.
  • Ran a read-only codex exec task.
  • Captured logs_2.sqlite state again.
  • No local SQLite mitigation trigger was installed.

Before codex exec:

app-server status: app-server stopped
row_count:         62346
max_id:            290140851
trigger_count:     0

logs_2.sqlite:      335183872 bytes
logs_2.sqlite-wal:  0 bytes
logs_2.sqlite-shm:  32768 bytes

After codex exec:

row_count:         62346
max_id:            290140851
trigger_count:     0

logs_2.sqlite:      335183872 bytes
logs_2.sqlite-wal:  0 bytes
logs_2.sqlite-shm:  32768 bytes

Watchdog report window:

Sample window: 2026-06-26 14:32:48Z to 14:40:55Z
Duration:      ~487 seconds
Samples:       317

Total Codex process bytes written:   171.1 MB
System disk write delta:             847.2 MB
Peak Codex write rate:               ~330 MB/min

Important detail: the report window still included desktop app shutdown tail activity at the beginning. Breaking down the sampled process writes:

Desktop app/app-server tail writes:  ~168.2 MB
codex exec CLI writes:               ~2.9 MB
command child writes:                ~4 KB

The desktop tail writes were concentrated before the app-server was fully gone. The later codex exec task only produced small session-file writes, and logs_2.sqlite / WAL / max(id) did not change.

This suggests the large persistent SQLite log write amplification is primarily tied to the desktop app-server path, not to non-interactive codex exec in this test. It also gives users a practical temporary workaround: quit the Desktop App and use codex exec for read-only / automation-style work when possible.

BigiKoCcc · 23 days ago

Additional macOS datapoint on Codex Desktop 26.623.42026 / build 4514.

Environment:

  • Platform: macOS arm64
  • Codex Desktop: 26.623.42026, build 4514
  • Embedded CLI: codex-cli 0.142.3
  • Active app-server process:

/Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled

  • App-server PID during sample: 45836
  • Process env includes RUST_LOG=warn
  • No raw feedback_log_body values are included here because they may contain private local paths, tool output, or conversation/session details.

The app-server process was holding open handles to the persistent log DB:

~/.codex/logs_2.sqlite
~/.codex/logs_2.sqlite-wal
~/.codex/logs_2.sqlite-shm

Current file sizes during the sample:

logs_2.sqlite      ~58 MB
logs_2.sqlite-wal  ~4.2 MB to ~6.1 MB during recent checks
logs_2.sqlite-shm  32 KB

SQLite health/state:

integrity_check: ok
journal_mode:    wal
page_count:      14932
freelist_count:  1463

Recent 60-second sample:

latest row timestamp: 2026-06-27 15:12:58 local time
last_60s_rows:        1165
last_60s_bytes:       2282208

Recent 10-minute level distribution:

TRACE  1107 rows  4257427 estimated bytes
DEBUG   141 rows   165815 estimated bytes
INFO     55 rows    61714 estimated bytes
WARN      9 rows     7731 estimated bytes

Top retained targets in the same 10-minute window:

TRACE log                                      577 rows
TRACE codex_api::sse::responses                254 rows
TRACE codex_app_server::outgoing_message        87 rows
TRACE hyper_util::client::legacy::pool          64 rows
TRACE hyper_util::client::legacy::client        57 rows
DEBUG codex_core::stream_events_utils           38 rows
DEBUG hyper_util::client::legacy::connect::http 38 rows
TRACE codex_mcp::connection_manager             24 rows
TRACE codex_client::transport                    9 rows, ~3.6 MB estimated

So this still reproduces for me on 26.623.42026 / build 4514 / embedded codex-cli 0.142.3: the persistent SQLite log sink continues to store high-volume TRACE and DEBUG rows even though the active app-server process has RUST_LOG=warn.

This looks consistent with the root-cause analysis above: the persistent SQLite sink appears to be filtering independently from RUST_LOG, so the newer 0.142.3 build still has the desktop app-server SQLite churn path.

Nicolas0315 · 23 days ago

Adding a current macOS Desktop 26.623.42026 / CLI 0.142.3 datapoint.

Snapshot time: 2026-06-28 11:26 JST

Environment:

  • Codex Desktop: 26.623.42026, build 4514
  • Codex CLI / app-server: 0.142.3
  • Platform: macOS arm64
  • codex doctor --json: overallStatus=ok
  • launchctl getenv RUST_LOG: warn

SQLite state:

logs_2.sqlite: 400M
logs_2.sqlite-wal: 57M
logs_2.sqlite-shm: 128K
PRAGMA quick_check: ok
PRAGMA journal_mode: wal
total rows: 109601

Persisted row levels:

TRACE: 83256
DEBUG: 12230
INFO: 11775
WARN: 2292
ERROR: 155

Top persisted (level, target) rows:

TRACE | log                              | 31915
TRACE | codex_mcp::connection_manager    | 30783
TRACE | codex_api::sse::responses        | 11175
INFO  | codex_core::stream_events_utils  | 8030
DEBUG | codex_core::stream_events_utils  | 4893

So on this build, TRACE rows are still the dominant persisted level in logs_2.sqlite even with launchd RUST_LOG=warn. This is not currently disk-filling on my machine, but it is still large enough to matter for startup/runtime pressure and backup/log maintenance.

Omitting raw log rows and local paths beyond the database filename.

RuntianLee · 22 days ago

This is a management project I developed for codex to overwrite logs. It includes functions for analyzing, mitigating, and deleting redundant logs, and the documentation explains the implementation steps and runtime logic in detail. I tested it on this machine and it works well, give it a try! [https://github.com/RuntianLee/codex-disk-guard](url)

RonZhu · 22 days ago

Follow-up from the same affected Mac after updating to the latest build currently available here.

Environment:

  • Codex app: 26.623.42026, build 4514
  • Embedded CLI: codex-cli 0.142.3
  • PATH CLI: codex-cli 0.142.3
  • Active desktop app-server: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID during sample: 207, started Mon Jun 29 09:57:24 2026
  • Process env: RUST_LOG=warn

Important note: I left my local SQLite mitigation triggers enabled for this check. They are still:

  • sample_log_inserts: retain at most about one row every 10 seconds.
  • trim_sampled_logs: keep only the newest 500 retained rows.

So this is not a raw insert-rate measurement. It is a protected-state check to see whether the current app-server is still producing persisted TRACE records after the 0.142.3 update.

Current retained state:

PRAGMA quick_check: ok
journal_mode: wal
row_count: 500
level distribution: TRACE 499, INFO 1
page_count: 10480
freelist_count: 10409

The retained rows are now dominated by the new active desktop app-server process:

pid:207 ... 48 retained rows from 2026-06-29 09:57:26 to 10:05:39 local time

30-second protected sample:

2026-06-29 10:05:59  max(id)=131738  latest=TRACE target=log
2026-06-29 10:06:09  max(id)=131739  latest=TRACE target=log
2026-06-29 10:06:19  max(id)=131740  latest=TRACE target=hyper_util::client::legacy::pool
2026-06-29 10:06:29  max(id)=131741  latest=TRACE target=hyper_util::client::legacy::pool

logs_2.sqlite-wal mtime advanced with each retained row in that sample. File sizes stayed bounded because of the local mitigation:

~/.codex/logs_2.sqlite      42926080 bytes
~/.codex/logs_2.sqlite-wal   4169472 bytes
~/.codex/logs_2.sqlite-shm     32768 bytes

The latest retained TRACE target=log rows are still mostly websocket/tungstenite noise such as Stream.poll_next / WebSocketStream.with_context, plus app-server dispatch/pool entries. I am still not pasting raw feedback_log_body rows beyond short target/category descriptions because they may contain private local/session details.

Conclusion from this machine: 26.623.42026 / build 4514 / codex-cli 0.142.3 still appears to feed TRACE-level events into the persistent SQLite sink despite RUST_LOG=warn. The local trigger mitigation keeps SSD writes bounded here, but it does not indicate that the upstream persistent TRACE source has stopped.

zyfasos · 21 days ago

Additional macOS datapoint after updating to Codex app 26.623.70822 / build 4559.

Environment:

  • Codex app: 26.623.70822, build 4559
  • Embedded CLI: codex-cli 0.142.4
  • Active app-server process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID during sample: 43548, started Tue Jun 30 09:34:09 2026
  • RUST_LOG=info
  • A local SQLite mitigation trigger existed before the test, so I temporarily removed it for a controlled 30-second sample, then restored it immediately afterward and truncated the WAL again.
  • No raw feedback_log_body values are included here because they may contain private local paths, tool output, or conversation/session details.

Controlled sample with the trigger disabled:

Sample window: 2026-06-30 09:35:20 CST to 09:35:50 CST
max(id):       20023980 -> 20026163 (+2183)
count(*):      38762 -> 39563 (+801)
WAL size:      0 -> 4,750,392 bytes during the sample

Rows visible in the sample window:

level  target                                     rows  estimated_bytes
TRACE  log                                        935   724050
TRACE  codex_api::sse::responses                  41    42578
TRACE  hyper_util::client::legacy::pool           18    4069
TRACE  codex_app_server::outgoing_message         15    2464
DEBUG  codex_core::stream_events_utils            14    22914
TRACE  codex_mcp::connection_manager              12    10233
TRACE  hyper_util::client::legacy::client         12    2676
DEBUG  hyper_util::client::legacy::connect::http  8     1860
DEBUG  log                                        8     496
INFO   codex_core::stream_events_utils            8     8883
INFO   feedback_tags                              8     9131
DEBUG  codex_client::default_client               5     5620
DEBUG  hyper_util::client::legacy::pool           5     1145
INFO   codex_client::custom_ca                    4     940
TRACE  hyper_util::client::legacy::connect::http  4     1144
TRACE  codex_api::endpoint::responses_websocket   3     318578
TRACE  codex_core::client                         3     2718
TRACE  codex_core::session::turn                  3     2724
WARN   codex_core_plugins::manifest               3     3114

After restoring the local trigger and running PRAGMA wal_checkpoint(TRUNCATE), the local state was:

trigger_present: block_trace_debug_logs
logs_2.sqlite-wal size: 0

A follow-up 30-second observation with the trigger enabled showed only retained INFO/WARN rows, while TRACE/DEBUG rows were not persisted by the local mitigation. This suggests build 4559 still produces persistent TRACE/DEBUG log churn when the local SQLite mitigation is removed.

RonZhu · 21 days ago

Follow-up from the same affected Mac after updating again.

Environment:

  • Codex app: 26.623.70822, build 4559
  • Embedded CLI: codex-cli 0.142.4
  • PATH CLI: codex-cli 0.142.4
  • Active desktop app-server: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID during sample: 412, started Tue Jun 30 10:09:01 2026
  • Process env: RUST_LOG=warn
  • codex_chronicle was also running (pid 532), but the latest retained SQLite rows below are dominated by the app-server process UUID for pid 412.

Important note: I left the local SQLite mitigation triggers enabled for this check:

sample_log_inserts
trim_sampled_logs

So this is a protected-state check, not a raw insert-rate measurement. On this machine those triggers retain at most about one row every 10 seconds and keep only the newest 500 retained rows.

Current retained SQLite state:

PRAGMA quick_check: ok
journal_mode: wal
row_count: 500
page_count: 10480
freelist_count: 10411
level distribution: TRACE 499, INFO 1

Recent retained rows are dominated by the active desktop app-server:

pid:412 ... 350 retained rows from 2026-06-30 10:09:03 to 2026-06-30 11:07:16 local time

30-second protected sample:

2026-06-30 11:06:16  max(id)=139110  latest=TRACE target=hyper_util::client::legacy::pool
2026-06-30 11:06:26  max(id)=139111  latest=TRACE target=log
2026-06-30 11:06:36  max(id)=139112  latest=INFO  target=codex_app_server::message_processor
2026-06-30 11:06:46  max(id)=139113  latest=TRACE target=log

logs_2.sqlite-wal mtime advanced with these retained rows. File sizes at the end of the check:

~/.codex/logs_2.sqlite      42926080 bytes
~/.codex/logs_2.sqlite-wal   8540792 bytes
~/.codex/logs_2.sqlite-shm     32768 bytes

Top retained targets at the end of the check:

TRACE log                                      488
TRACE hyper_util::client::legacy::pool           6
TRACE hyper_util::client::legacy::client         4
INFO  codex_app_server::message_processor        1
TRACE codex_app_server::message_processor        1

I am intentionally not pasting raw feedback_log_body values. One retained non-TRACE row appeared to include a response/token-like payload, which is a useful privacy signal: this persistent SQLite sink can contain local/session-sensitive data, not just harmless category names.

Conclusion from this machine: 26.623.70822 / build 4559 / codex-cli 0.142.4 still appears to feed TRACE-level events into the persistent SQLite sink despite RUST_LOG=warn. The local mitigation keeps retained rows and SSD growth bounded here, but it does not show that the upstream persistent TRACE source has stopped.

lock-down · 20 days ago

<img width="2546" height="960" alt="Image" src="https://github.com/user-attachments/assets/5c39b2ae-5dd0-4fae-a141-65f33cd1e12d" />
Already fix?

Lynch715 · 20 days ago

Additional macOS datapoint: the high-frequency TRACE writes still reproduce after setting RUST_LOG=error with launchctl and fully restarting the Codex app via Cmd+Q.

Environment:

  • macOS: 26.6 (25G5043d), arm64
  • Codex app: 26.623.70822, build 4559
  • Embedded CLI: codex-cli 0.142.4
  • Active app-server command: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • Active app-server PID during sample: 19397, started Wed Jul 1 09:59:43 2026
  • launchctl print gui/501 shows RUST_LOG => error
  • No SQLite triggers remain on logs

20-second sample after restart:

before=43758|40323326|33256|40323326|1782871246
after=43781|40324184|33232|40324184|1782871256
wal_before=8178232|1782871246
wal_after=8178232|1782871257

Column order: COUNT(*)|MAX(id)|SUM(level="TRACE")|MAX(trace id)|MAX(ts). MAX(id) and MAX(trace id) both continue to increase; WAL mtime also advances.

Rows with id > before_max_id were mostly TRACE:

TRACE  log                                        753
DEBUG  log                                        17
TRACE  hyper_util::client::legacy::pool           16
TRACE  hyper_util::client::legacy::client         12
DEBUG  hyper_util::client::legacy::connect::http  8
INFO   feedback_tags                              7
TRACE  codex_api::sse::responses                  5
TRACE  codex_app_server::message_processor        4
TRACE  codex_app_server::outgoing_message         4
TRACE  hyper_util::client::legacy::connect::http  4

This suggests the desktop app-server SQLite feedback log path is still persisting TRACE-level records despite RUST_LOG=error being present in the GUI launchd environment and the app being restarted.

RonZhu · 19 days ago

Follow-up from the same affected Mac after updating to a newer Desktop build.

Environment:

  • Platform: macOS 27.0 (26A5368g), arm64
  • Codex app: 26.623.81905, build 4598
  • Embedded CLI: codex-cli 0.142.5
  • PATH CLI: codex-cli 0.142.5
  • Active desktop app-server: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • App-server PID during check: 39970, started Wed Jul 1 12:33:06 2026
  • Local SQLite mitigation triggers were still enabled: sample_log_inserts, trim_sampled_logs

Important note: this is a protected-state check, not a raw insert-rate measurement. I did not remove the local mitigation this time. On this machine those triggers retain at most about one row every 10 seconds and keep only the newest 500 retained rows.

Current retained SQLite state:

PRAGMA quick_check: ok
journal_mode: wal
row_count: 500
trace_rows: 500
page_count: 10480
freelist_count: 10378
page_size: 4096
latest retained row: 2026-07-01 13:13:46 Asia/Shanghai

30-second protected sample:

before: count=500 max_id=148375 trace_rows=500 max_trace_id=148375 max_ts=1782882765
 after: count=500 max_id=148378 trace_rows=500 max_trace_id=148378 max_ts=1782882796

Top retained targets after the sample:

TRACE log                                  480
TRACE hyper_util::client::legacy::pool       9
TRACE hyper_util::client::legacy::client     7
TRACE codex_app_server::message_processor    3
TRACE rmcp::service                          1

File sizes at the end of the check:

~/.codex/logs_2.sqlite      42926080 bytes
~/.codex/logs_2.sqlite-wal   8157632 bytes
~/.codex/logs_2.sqlite-shm     32768 bytes

Conclusion from this machine: 26.623.81905 / build 4598 / codex-cli 0.142.5 does not look fixed yet. Even with the local sampled-retention trigger active, retained rows are still 500/500 TRACE and max_trace_id continues to advance. The local mitigation is containing retained rows and disk growth here; it is not evidence that the upstream Desktop app-server stopped feeding TRACE events into the persistent SQLite sink.

I am not pasting raw feedback_log_body values because they may include local paths, tool output, or conversation/session details.

lock-down · 19 days ago
Follow-up from the same affected Mac after updating to a newer Desktop build.同一台受影响的 Mac 在更新到较新的桌面版本后出现了后续问题。 Environment:  环境: Platform: macOS 27.0 (26A5368g), arm64平台:macOS 27.0 ( 26A5368g ), arm64 Codex app: 26.623.81905, build 4598Codex 应用: 26.623.81905 ,版本 4598 Embedded CLI: codex-cli 0.142.5嵌入式命令行界面: codex-cli 0.142.5 PATH CLI: codex-cli 0.142.5PATH CLI: codex-cli 0.142.5 Active desktop app-server: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled已启用桌面应用服务器: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled App-server PID during check: 39970, started Wed Jul 1 12:33:06 2026应用服务器进程 ID(PID): 39970 ,启动时间: Wed Jul 1 12:33:06 2026 * Local SQLite mitigation triggers were still enabled: sample_log_inserts, trim_sampled_logs本地 SQLite 缓解触发器仍然启用: sample_log_insertstrim_sampled_logs Important note: this is a protected-state check, not a raw insert-rate measurement. I did not remove the local mitigation this time. On this machine those triggers retain at most about one row every 10 seconds and keep only the newest 500 retained rows.重要提示:这是受保护状态检查,并非原始插入率测量。这次我没有移除本地缓解措施。在这台机器上,这些触发器最多每 10 秒保留一行数据,并且只保留最新的 500 行。 Current retained SQLite state:当前保留的 SQLite 状态: `` PRAGMA quick_check: ok journal_mode: wal row_count: 500 trace_rows: 500 page_count: 10480 freelist_count: 10378 page_size: 4096 latest retained row: 2026-07-01 13:13:46 Asia/Shanghai ` 30-second protected sample:30 秒保护采样: ` before: count=500 max_id=148375 trace_rows=500 max_trace_id=148375 max_ts=1782882765 after: count=500 max_id=148378 trace_rows=500 max_trace_id=148378 max_ts=1782882796 ` Top retained targets after the sample:样本筛选后保留的主要目标: ` TRACE log 480 TRACE hyper_util::client::legacy::pool 9 TRACE hyper_util::client::legacy::client 7 TRACE codex_app_server::message_processor 3 TRACE rmcp::service 1 ` File sizes at the end of the check:检查结束时的文件大小: ` ~/.codex/logs_2.sqlite 42926080 bytes ~/.codex/logs_2.sqlite-wal 8157632 bytes ~/.codex/logs_2.sqlite-shm 32768 bytes ` Conclusion from this machine: 26.623.81905 / build 4598 / codex-cli 0.142.5 does not look fixed yet. Even with the local sampled-retention trigger active, retained rows are still 500/500 TRACE and max_trace_id continues to advance. The local mitigation is containing retained rows and disk growth here; it is not evidence that the upstream Desktop app-server stopped feeding TRACE events into the persistent SQLite sink.从这台机器得出的结论: 26.623.81905 / build 4598 / codex-cli 0.142.5 版本似乎尚未修复。即使启用了本地采样保留触发器,保留的行数仍然是 500/500 TRACE,并且 max_trace_id 持续增加。本地缓解措施控制了保留的行数和磁盘增长;但这并不能证明上游桌面应用服务器已停止向持久性 SQLite 存储体提供 TRACE 事件。 I am not pasting raw feedback_log_body values because they may include local paths, tool output, or conversation/session details.我不粘贴原始的 feedback_log_body` 值,因为它们可能包含本地路径、工具输出或对话/会话详细信息。

I tested 0.142.5 and it was not fixed+11111111111111

XiaDao · 19 days ago

Follow-up after updating to 0.142.5, which includes #30771:

I updated to Codex CLI 0.142.5, which includes the #30771 websocket trace fix, and collected another diagnostic window.

The previous “full Responses WebSocket request payload written to trace logs” symptom appears to be improved: in the new window, the largest log body is only about 53 KB, and the main recent log targets are not dominated by codex_api::endpoint::responses_websocket.

However, I still observe residual write amplification while Codex is mostly idle:

  • Codex App: 26.623.81905
  • Codex CLI: 0.142.5
  • Window duration: about 23 minutes
  • Codex process write delta: ~1.38 GB
  • System SSD write delta: ~3.24 GB
  • Codex average CPU: ~0.3%
  • Low-CPU high-write samples: 72
  • Peak Codex write rate: ~4192 MB/min
  • ~/.codex/logs_2.sqlite rows: 86059 -> 87005 (+946)
  • logs_2.sqlite max id: 296657192 -> 296822464 (+165272)
  • WAL size: ~4.5 MB -> ~7.7 MB
  • Database size stayed flat at ~335 MB
  • Report-window log body total: ~2.3 MB
  • Largest single log body: ~53 KB
  • Main report-window targets: codex_api::sse::responses, codex_core::spawn, codex_mcp::connection_manager, and log

So my current understanding is:

#30771 seems to fix one important payload-size source, but there may still be another source of write amplification, possibly from high-frequency log insertion/pruning, WAL/checkpoint behavior, or bridged log events. The key signal is that max_id increased by ~165k while the retained row count only increased by ~946 and the retained log body volume was small.

One caveat: the single largest spike in this window was attributed to a child tool process, so that specific spike may not be the Codex core logger itself. But even excluding that spike, the Codex core process still produced substantial low-CPU writes over the window.

Please let me know if there is a specific trace/log setting or diagnostic command you would like me to run on 0.142.5.

buaaer001-droid · 18 days ago

I can reproduce this on macOS as well.

Environment:

  • macOS: 26.5, build 25F71, arm64
  • Codex app: 26.623.70822, build 4559
  • Embedded CLI: codex-cli 0.142.4
  • DB: ~/.codex/logs_2.sqlite, journal mode WAL

Observed before mitigation:

  • logs_2.sqlite: ~38 MB
  • logs_2.sqlite-wal: grew from ~4.1 MB to ~4.9 MB during observation
  • rows: 9866 -> 10171 within a short sample
  • max(id): 813412 -> 819837
  • TRACE rows dominated the table: ~7979 TRACE rows out of ~9866 total
  • recent 60s sample was dominated by:
  • TRACE log: 1126 rows
  • TRACE codex_api::sse::responses: 88 rows
  • TRACE codex_app_server::outgoing_message: 46 rows

A local SQLite trigger that ignores only TRACE inserts stopped new TRACE growth:

  • TRACE max(id) stopped at 829443
  • later samples showed only DEBUG/INFO/WARN continuing
  • no raw feedback_log_body contents pasted because they may contain private conversation/tool data

This looks like the same persistent SQLite TRACE churn described in #29532, still reproducible on Codex app 26.623.70822 / embedded CLI 0.142.4.

zyfasos · 17 days ago

Additional macOS datapoint after updating to Codex app 26.623.101652 / build 4674.

Environment:

  • Codex app: 26.623.101652, build 4674
  • Embedded CLI: codex-cli 0.142.5
  • Active app-server command: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • RUST_LOG was unset in the launchd environment at the time of the check.
  • A local SQLite mitigation trigger existed before the test, so I temporarily removed it for a controlled 30-second sample, then restored it immediately afterward and truncated the WAL again.
  • No raw feedback_log_body values are included here because they may contain private local paths, tool output, or conversation/session details.

Notable process state after a full app restart/update:

Two codex app-server processes were running and both held open handles to logs_2.sqlite, logs_2.sqlite-wal, and logs_2.sqlite-shm.

PID    PPID  started
94151  1     Fri Jul  3 12:07:17 2026
94919  94887 Fri Jul  3 12:07:36 2026

Controlled sample with the trigger disabled:

Sample window: 2026-07-03 12:09:43 CST to 12:10:13 CST
max(id):       20053926 -> 20054522 (+596)
count(*):      34196 -> 34792 (+596)
WAL size:      0 -> 1,833,432 bytes during the sample

Rows visible in the sample window:

level  target                                                            rows  estimated_bytes
TRACE  log                                                               577   175550
DEBUG  log                                                               8     419
TRACE  codex_api::sse::responses                                         3     3212
TRACE  hyper_util::client::legacy::pool                                  3     665
INFO   codex_app_server_transport::transport::remote_control::websocket  1     624
INFO   codex_core::stream_events_utils                                   1     4630
INFO   feedback_tags                                                     1     133
TRACE  codex_app_server::outgoing_message                                1     160
WARN   codex_app_server_transport::transport::remote_control::websocket  1     935

Rows by process UUID in the same sample window:

process_uuid                                    rows  trace_rows  debug_rows
pid:94151:1af60d6a-3dc5-4608-bc97-d376c47db0ba  315   315         0
pid:94919:1b9d9fd8-2306-4905-b74d-829cfe067eab  281   269         8

After restoring the local mitigation trigger and running PRAGMA wal_checkpoint(TRUNCATE), the local state was:

trigger_present: block_trace_debug_logs
logs_2.sqlite-wal size: 0

A follow-up 30-second observation with the trigger enabled persisted only INFO/WARN rows, while TRACE/DEBUG rows were not persisted by the local mitigation.

This suggests 0.142.5 / build 4674 may have improved the large websocket request-payload trace symptom from #30771, but the broader persistent TRACE/DEBUG SQLite churn still reproduces when the local SQLite mitigation is removed. In this run, both active app-server processes contributed rows.

RonZhu · 15 days ago

Follow-up from the same affected Mac after updating to a newer Desktop build again.

Environment:

  • Platform: macOS 27.0 (26A5368g), arm64
  • Codex app: 26.623.101652, build 4674
  • Embedded CLI: codex-cli 0.142.5
  • PATH CLI: codex-cli 0.142.5
  • Active desktop app-server: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • Active desktop app-server PID during check: 98496, started Mon Jul 6 10:49:08 2026
  • launchctl getenv RUST_LOG returned empty/unset during this check
  • A separate stdio app-server was also present: /Users/ron/.local/bin/codex app-server --listen stdio://, PID 3728
  • Local SQLite mitigation triggers were still enabled: sample_log_inserts, trim_sampled_logs

Important note: this is another protected-state check, not a raw insert-rate measurement. I did not remove the local mitigation this time. On this machine those triggers retain at most about one row every 10 seconds and keep only the newest 500 retained rows.

Current retained SQLite state after the sample:

PRAGMA quick_check: ok
journal_mode: wal
row_count: 500
trace_rows: 500
page_count: 32769
freelist_count: 32671
page_size: 4096
latest retained row: 2026-07-06 11:12:07 Asia/Shanghai

30-second protected sample:

before: count=500 max_id=189220 trace_rows=500 max_trace_id=189220 max_ts=1783307497 latest=2026-07-06 11:11:37
 after: count=500 max_id=189223 trace_rows=500 max_trace_id=189223 max_ts=1783307527 latest=2026-07-06 11:12:07

File sizes at the end of the check:

~/.codex/logs_2.sqlite      134221824 bytes
~/.codex/logs_2.sqlite-wal    4185952 bytes
~/.codex/logs_2.sqlite-shm      32768 bytes

Top retained targets after the sample:

TRACE log                                  480
TRACE hyper_util::client::legacy::pool      15
TRACE hyper_util::client::legacy::client     4
TRACE codex_app_server::outgoing_message     1

The newest retained rows immediately after the sample were still from the active Desktop app-server process UUID:

189225  2026-07-06 11:12:27  TRACE  log  pid:98496:06d227f2-204d-4c82-a197-bd163eb74d1f
189224  2026-07-06 11:12:17  TRACE  log  pid:98496:06d227f2-204d-4c82-a197-bd163eb74d1f
189223  2026-07-06 11:12:07  TRACE  log  pid:98496:06d227f2-204d-4c82-a197-bd163eb74d1f
189222  2026-07-06 11:11:57  TRACE  log  pid:98496:06d227f2-204d-4c82-a197-bd163eb74d1f

Conclusion from this machine: 26.623.101652 / build 4674 / codex-cli 0.142.5 still does not look fully fixed. The large websocket request-payload trace symptom may be improved, as others noted for #30771, but the broader persistent SQLite TRACE sink still appears active: retained rows remain 500/500 TRACE and max_trace_id continues to advance under the local sampled-retention trigger.

I am not pasting raw feedback_log_body values because they may include local paths, tool output, or conversation/session details.

tangleo203 · 11 days ago

Additional reproduction on ChatGPT-integrated Codex / 0.144.0-alpha.4

I can still reproduce the bridged TRACE target=log persistence on a newer macOS build that embeds Codex inside the ChatGPT app.

Environment

  • macOS, Apple Silicon
  • ChatGPT app: 26.707.31428 (build 5059)
  • Embedded binary: /Applications/ChatGPT.app/Contents/Resources/codex
  • Embedded CLI version: codex-cli 0.144.0-alpha.4
  • SQLite DB: ~/.codex/logs_2.sqlite

Evidence collected before installing any local workaround

The current app-server process persisted 436 rows with target=log between:

2026-07-10 08:27:01 +0800
2026-07-10 08:27:05 +0800

Example sanitized messages included:

TRACE log: deregistering event source from poller
TRACE log: shouldn't retry!

At the time of inspection, the retained target counts included:

log                              2333
codex_api::sse::responses        1654
hyper_util::client::legacy::pool  547

No retained rows were found for codex_otel.log_only or codex_otel.trace_safe, so that part of the filtering appears effective. However, bridged target=log events are still reaching SQLite, despite #29599 being intended to reject them inside the sink.

This appears to be either:

  1. a regression after #29599 / 0.143.0, or
  2. a different logging path in the ChatGPT-integrated app build that bypasses the sink-level metadata.target() == "log" guard.

Local confirmation/workaround

After the measurement, I installed a SQLite BEFORE INSERT ... RAISE(IGNORE) trigger for the noisy targets. A test insert was ignored, and normal non-blocked log IDs continued advancing while the blocked-target maximum ID stayed unchanged. This is only a local workaround; filtering before formatting/queueing remains preferable.

Raw payloads, thread IDs, local paths, and conversation contents are intentionally omitted.

RonZhu · 8 days ago

Follow-up from the same affected Mac after updating to the newer ChatGPT-integrated Codex build.

Environment:

  • Platform: macOS 27.0 (26A5378j), arm64
  • ChatGPT app: 26.707.61608, build 5200
  • Embedded binary: /Applications/ChatGPT.app/Contents/Resources/codex
  • Embedded CLI version: codex-cli 0.144.0-alpha.4
  • command -v codex now resolves to the ChatGPT embedded binary on this machine
  • The previous standalone /Applications/Codex.app/Contents/Resources/codex binary was not present during this check
  • Active ChatGPT-integrated app-server: /Applications/ChatGPT.app/Contents/Resources/codex -c features.code_mode_host=true app-server --analytics-default-enabled
  • Active ChatGPT-integrated app-server PID during check: 92069, started Mon Jul 13 10:03:30 2026
  • A separate stdio app-server was also present: ~/.local/bin/codex app-server --listen stdio://, PID 89531
  • launchctl getenv RUST_LOG returned empty/unset during this check
  • Local SQLite mitigation triggers were still enabled: sample_log_inserts, trim_sampled_logs

Important note: this is another protected-state check, not a raw insert-rate measurement. I did not remove the local mitigation this time. On this machine those triggers retain at most about one row every 10 seconds and keep only the newest 500 retained rows.

Current retained SQLite state after the sample:

PRAGMA quick_check: ok
journal_mode: wal
row_count: 500
trace_rows: 451
debug_rows: 33
info_rows: 10
warn_rows: 6
error_rows: 0
page_count: 32769
freelist_count: 32649
page_size: 4096
latest retained row: 2026-07-13 10:33:48 Asia/Shanghai

30-second protected sample:

before: count=500 max_id=221476 trace_rows=452 max_trace_id=221475 debug_rows=32 info_rows=10 warn_rows=6 error_rows=0 latest=2026-07-13 10:33:18
 after: count=500 max_id=221479 trace_rows=451 max_trace_id=221479 debug_rows=33 info_rows=10 warn_rows=6 error_rows=0 latest=2026-07-13 10:33:48

File sizes at the end of the check:

~/.codex/logs_2.sqlite       134221824 bytes
~/.codex/logs_2.sqlite-wal    44388912 bytes
~/.codex/logs_2.sqlite-shm       32768 bytes

Top retained targets after the sample:

TRACE  log                                   333
TRACE  hyper_util::client::legacy::pool       27
TRACE  codex_app_server::outgoing_message     25
TRACE  hyper_util::client::legacy::client     25
TRACE  codex_api::sse::responses              24
TRACE  codex_app_server::message_processor    17
DEBUG  codex_http_client::default_client      15
DEBUG  codex_core::stream_events_utils        10
DEBUG  opentelemetry-otlp                      8
INFO   codex_http_client::custom_ca            6
WARN   codex_app_server_transport::transport::remote_control::websocket  5

The newest retained rows immediately after the sample included new TRACE rows from both the ChatGPT-integrated app-server and the stdio app-server:

221479  2026-07-13 10:33:48  TRACE  codex_app_server::message_processor  pid:89531:7334f365-0926-407f-aac9-abe8fc58abf9
221478  2026-07-13 10:33:38  TRACE  codex_api::sse::responses            pid:92069:71bd96dc-8afa-4d14-85b4-d909fc2345a0
221477  2026-07-13 10:33:28  DEBUG  codex_http_client::default_client    pid:92069:71bd96dc-8afa-4d14-85b4-d909fc2345a0
221476  2026-07-13 10:33:18  DEBUG  codex_core::stream_events_utils      pid:92069:71bd96dc-8afa-4d14-85b4-d909fc2345a0
221475  2026-07-13 10:33:08  TRACE  codex_app_server::outgoing_message   pid:92069:71bd96dc-8afa-4d14-85b4-d909fc2345a0

Conclusion from this machine: the old 500/500 TRACE protected-state symptom has changed in the ChatGPT-integrated 0.144.0-alpha.4 build: retained rows now include DEBUG/INFO/WARN as well. However, the broader issue still does not look fully fixed here. max_trace_id continued to advance during the protected sample, and TRACE target=log remains the largest retained target. This matches the concern in the newer ChatGPT-integrated reports: part of the older filtering appears improved, but bridged TRACE/log-style events still reach the persistent SQLite DB.

I am not pasting raw feedback_log_body values because they may include local paths, tool output, or conversation/session details.

0xdevalias · 8 days ago
> Our series of fixes for this problem are in the latest shipping desktop app, CLI, and IDE extension. Not quite yet. 0.144.1 does not have #31789, #31790, #31791, and #31792. 0.145.0-alpha.4 includes them, so 0.145.0 likely will too. Also, please see #32496. A different root cause is causing about 1.3 TB/year in unnecessary writes, according to the numbers in the issue. (Much less than was on this issue.) Codex is continually rewriting models_cache.json and scope_v3.json. _Originally posted by @darlingm in https://github.com/openai/codex/issues/28224#issuecomment-4952520973_
Freyliu0516 · 7 days ago

I’ve completed an independent reference implementation and validation effort for the persistent SQLite TRACE/DEBUG issue described here.

Repository:

https://github.com/Freyliu0516/Codex-Log-Doctor

Proposed upstream change

The upstream patch is deliberately small and separate from the user-side diagnostic tool:

  1. change the persistent SQLite sink’s default level from TRACE to WARN;
  2. keep the existing target-specific exclusions;
  3. filter low-level events before they are formatted, queued, or sent to SQLite;
  4. add a regression test that emits 100,000 TRACE events and 100,000 DEBUG events;
  5. verify that SQLite retains only the expected WARN event.

Reference patch:

https://github.com/Freyliu0516/Codex-Log-Doctor/tree/main/upstream

The independent tool does not patch or replace an installed Codex binary. The upstream/ directory exists only as a reviewable reference implementation.

Validation

The patched Codex source was tested against the pinned upstream base:

  • codex-state primary tests: 151 passed;
  • binary tests: 3 passed;
  • doctests: 1 passed;
  • persistence regression:
  • 100,000 TRACE iterations;
  • 100,000 DEBUG iterations;
  • 0 unexpected rows persisted;
  • the expected WARN row was retained.

The separate Codex Log Doctor repository also passed:

  • formatting;
  • workspace-wide Clippy;
  • all workspace tests;
  • release builds on Linux, macOS, and Windows;
  • supply-chain checks;
  • source-install smoke tests;
  • upstream patch drift checks.

The repository additionally contains 18 deterministic component and failure-mode scenarios covering SQLite/WAL contention, queue saturation, backup and rollback, interrupted operations, unsupported schemas, and report redaction. These are supporting tests, not a claim that all 18 scenarios exercise the complete Codex app-server pipeline.

Public CI evidence is linked from the merged initial implementation PR:

https://github.com/Freyliu0516/Codex-Log-Doctor/pull/1

User-side mitigation

The tool can install a fingerprint-gated SQLite BEFORE INSERT trigger that rejects TRACE rows. It requires:

  • an exact supported schema fingerprint;
  • no detected Codex process using the database;
  • exclusive SQLite access;
  • sufficient disk space;
  • a verified SQLite backup;
  • explicit --apply;
  • rollback metadata and post-operation integrity checks.

This is intended only as a reversible workaround. It reduces retained TRACE rows, MAX(id) growth, WAL writes, indexing, and subsequent pruning, but it does not eliminate upstream event construction, formatting, queueing, transactions, or attempted INSERT execution.

Early filtering in Codex remains the preferred fix.

Request

Would the Codex team be open to reviewing the persistence-filter approach?

If changing the persistent SQLite default from TRACE to WARN is consistent with the intended feedback and diagnostics behavior, I would appreciate guidance on whether the team would invite a focused upstream PR limited to:

  • codex-rs/state/src/log_db.rs;
  • the SQLite sink regression test;
  • any required documentation or configuration updates.

I’m also happy to adjust the proposed target-specific policy if there are operational events that the feedback pipeline must continue retaining below WARN.

fujiwarakasei · 5 days ago

I can still reproduce significant persistent SQLite TRACE churn on the current ChatGPT-integrated Codex desktop build, and I think this deserves clarification after #28224 was closed.

Environment

  • Platform: macOS / Apple Silicon
  • App: /Applications/ChatGPT.app
  • ChatGPT.app version: 26.707.72221
  • Build: 5307
  • Bundled Codex CLI: codex-cli 0.144.2
  • Primary DB: ~/.codex/logs_2.sqlite
  • Also observed project-scoped CODEX_HOME DBs such as client-hub-codex-home/logs_2.sqlite

Controlled test

I had been using a local SQLite stopgap trigger:

CREATE TRIGGER IF NOT EXISTS block_log_inserts
BEFORE INSERT ON logs
BEGIN
  SELECT RAISE(IGNORE);
END;

With the trigger enabled, short samples show:

  • id_delta=0
  • count_delta=0
  • WAL stable

I then temporarily removed the trigger for a controlled test and restored it immediately afterward.

Result: within roughly a one-minute active Codex window, the global ~/.codex/logs_2.sqlite accumulated about 2.6k rows and the WAL grew to about 4.15 MiB.

Dominant persisted targets were still TRACE/DEBUG-style internal plumbing:

  • TRACE codex_api::sse::responses
  • TRACE codex_mcp::connection_manager
  • TRACE codex_app_server::outgoing_message
  • TRACE hyper_util::client::legacy::*
  • DEBUG codex_core::stream_events_utils

After restoring the trigger, another short sample returned to:

  • id_delta=0
  • count_delta=0
  • WAL stable

Why I am posting

#28224 was closed as fixed, but the current shipping desktop app on my machine still bundles codex-cli 0.144.2. From the discussion around #28224, it sounds like the more relevant logging fixes (#31789, #31790, #31791, #31792) are expected in the 0.145.0-alpha.4+ line, not necessarily in this bundled desktop version.

So I would like to clarify:

  1. Is this residual persistent TRACE/DEBUG SQLite churn considered expected behavior?
  2. Which desktop app / bundled CLI version should include the full fix for #31789-#31792?
  3. Is there an official threshold for acceptable idle/active Codex local disk writes?
  4. Should users keep local mitigations like block_log_inserts until the bundled desktop CLI reaches the fixed line?
  5. Can OpenAI add an I/O regression test for idle and active Codex usage, so this class of issue does not regress silently?

I would also encourage other affected users to share comparable measurements with:

  • app version/build
  • bundled CLI version
  • platform
  • sample duration
  • MAX(id) delta
  • retained row delta
  • WAL byte delta
  • top persisted log targets
friday-james · 4 days ago

Fresh measurements on codex-cli 0.144.3 (Linux/ext4), plus a minimal tested patch and an A/B benchmark. TL;DR: most of the remaining churn is flush policy, not log content — batching the sink by bytes/severity instead of every 2 s cuts its physical writes ~5x on a steady-state workload, down to SQLite's WAL+checkpoint double-write floor, with zero change to what /feedback sees.

Measurements: the writes are flush overhead, not content

Four resumed TUI sessions left idle; write rates from /proc/<pid>/io deltas, content attribution from querying logs_2.sqlite (read-only) for rows inserted inside the same instrumented window:

| metric | value |
|---|---|
| physical writes in a 59 s idle window (2 busiest processes) | 28.2 MB |
| log rows retained in that same window | 630 rows / 774 KB |
| physical-to-retained write amplification | ~36x |
| combined idle write rate, 4 sessions | ~353 KB/s ≈ 30 GB/day |
| one idle session running 9.3 days | 123 GB lifetime writes |

The DB itself stays at ~25 MB — retention caps work. The wear comes from the durability policy: LOG_FLUSH_INTERVAL = 2s means ~43,000 transactions/day/process, each paying WAL page images + (at retention-cap steady state, which every long-lived session reaches) the windowed prune DELETE inside the same transaction.

Row-level attribution also shows why target muting (#29457, #29599, #31789, #31791) can't converge: after accounting for those mutes, idle traffic is dominated by codex's own targets — codex_app_server::outgoing_message (TRACE), codex_api::sse::responses (TRACE), codex_core::stream_events_utils (DEBUG), feedback_tags (INFO). Muting those defeats /feedback; keeping them keeps the churn. The reasoning that closed #23275 ("bounding individual call sites is brittle and misses future tracing events") applies equally to per-target filters.

Patch: flush by bytes/severity/60 s instead of every 2 s

Branch: https://github.com/friday-james/codex-1/tree/fix/log-db-write-churn — 3 files, +127/−9, mostly tests.

  • Flush the sink buffer on any of: ~1 MiB of estimated pending content, a 60 s tick, or a WARN/ERROR entry (flushed immediately, so crash-relevant diagnostics still reach disk right away).
  • /feedback already calls log_db.flush().await before reading (feedback_processor.rs), so feedback content is byte-identical, even mid-session.
  • LogEntry::estimated_bytes() is factored out and shared by the sink buffer and the insert path, so the write-side threshold and partition budgets agree.
  • Acknowledged trade-off: on SIGKILL, up to 60 s of TRACE/DEBUG tail can be lost (WARN/ERROR are not affected, and any explicit flush path is not affected). Today's policy loses up to 2 s.

A/B benchmark (each phase an isolated process)

Harness: https://github.com/friday-james/codex-1/tree/bench/log-db-write-churn (state/examples/write_churn_bench.rs). It replays the measured idle profile — 5.3 rows/s, ~1.2 KiB/row, thread partition pre-filled past its retention cap (steady state of a long-lived session) — for 3 minutes per policy, measuring /proc/self/io write_bytes. Two runs, results identical to ±0.2%:

old policy (2 s / 128 rows):        14.5 MB in 180 s  ->  7.02 GB/day
new policy (60 s / 1 MiB / sev):     2.9 MB in 180 s  ->  1.42 GB/day   (~4.9x less)

The new policy's 2.9 MB against 1.17 MB of raw content is SQLite's WAL-then-checkpoint double write plus prune/B-tree overhead — i.e. the patch removes nearly all removable churn; going lower requires persisting less content or relaxing durability guarantees. Note the benchmark is single-process and therefore conservative: live sessions share one logs_2.sqlite across processes, where checkpoint contention pushes the old policy 2–3x higher than the bench (and in the limit produces the unbounded-WAL growth reported in #28997).

Happy to open this as a PR per the invitation policy in contributing.md, or the approach is free to take as-is. Two further options if there's interest: prune hysteresis (once a partition crosses its cap, delete down to ~75% so steady-state inserts don't re-run the windowed DELETE every batch), and honoring an env override for the sink filter, which several reports expected RUST_LOG to do (#29463, #31111).

cc @jif-oai @charley-oai

papperrollinggery · 4 days ago

Request for clarification: current shipping build still lacks the broader SQLite fix

Following up with the current shipping macOS build:

  • ChatGPT/Codex app: 26.707.91948, build 5440
  • Bundled CLI: codex-cli 0.144.5
  • PATH CLI: codex-cli 0.144.3
  • npm stable: 0.144.5

The rust-v0.144.5 release contains only the dangerous-command detection fix in #33455. Its persistent log filter still uses:

Targets::new().with_default(LevelFilter::TRACE)

Source: https://github.com/openai/codex/blob/rust-v0.144.5/codex-rs/state/src/log_db.rs

The 0.144.4...0.144.5 release comparison also does not include #31789, #31790, #31791, or #31792. This appears inconsistent with the statement in #28224 that the series of fixes was already in the latest shipping desktop app, CLI, and IDE extension.

My local SQLite database is currently protected by this reversible stopgap:

CREATE TRIGGER block_log_inserts
BEFORE INSERT ON logs
BEGIN
  SELECT RAISE(IGNORE);
END;

Protected-state verification on the current build shows rows=0, seq=0, and max(id)=0. I did not remove the trigger for another raw sample because the shipping 0.144.5 source contains no relevant persistent-log change. I am not posting any raw feedback_log_body values because they may contain private paths, command fragments, tool output, or conversation context.

Could the maintainers please clarify:

  1. Is LevelFilter::TRACE still the intended production default for the persistent SQLite feedback log?
  2. Which exact stable CLI version and desktop build will contain the complete fix, including the relevant target/callsite reductions and any write-flush policy change?
  3. Is there a planned ETA or release line for that fix?
  4. Until that version ships, should affected users continue using a BEFORE INSERT ... RAISE(IGNORE) trigger?
  5. If the trigger is not recommended, what is the officially supported mitigation that prevents excessive writes without losing essential /feedback diagnostics?
  6. Can a regression test or documented acceptable idle/active write threshold be added so users can verify the fix?

A version-specific answer would help users know when it is safe to remove the trigger and restore normal persistent diagnostic logging.

RonZhu · 1 day ago

Follow-up after updating this Mac to the current ChatGPT-integrated Codex build.

Environment now:

  • Platform: macOS 27.0 (26A5378n), Apple Silicon / arm64
  • App: /Applications/ChatGPT.app
  • ChatGPT app: 26.715.31925, build 5551
  • codex resolves to: /Applications/ChatGPT.app/Contents/Resources/codex
  • CLI: codex-cli 0.145.0-alpha.18
  • Old standalone /Applications/Codex.app is not present on this machine
  • RUST_LOG is unset

I kept the local SQLite mitigation in place for this check. The active triggers are still:

sample_log_inserts
trim_sampled_logs

So this is a protected-state verification only; I did not remove the mitigation for another raw write-churn sample, and I am not posting raw feedback_log_body values publicly.

Current protected-state sample from ~/.codex/logs_2.sqlite:

quick_check:     ok
journal_mode:    wal
rows:            500
TRACE rows:      104
DEBUG rows:      128
INFO rows:       259
WARN rows:       9
ERROR rows:      0
sqlite size:     134,221,824 bytes
wal size:        4,194,192 bytes
page_count:      32769
freelist_count:  32650
page_size:       4096

30-second retained-row sample with the mitigation still enabled:

max(id):        240689 -> 240692  (+3)
rows:           500 -> 500
TRACE rows:     105 -> 104
max TRACE id:   240689 -> 240689
sqlite size:    unchanged at 134,221,824 bytes
wal size:       unchanged at 4,194,192 bytes

Newest retained rows in that sample were DEBUG codex_http_client::default_client and INFO codex_http_client::custom_ca; the newest retained TRACE row stayed at id 240689 (TRACE codex_app_server::message_processor). The retained sample still includes TRACE entries from codex_app_server::message_processor, codex_api::sse::responses, and codex_app_server::outgoing_message, but I cannot infer the unmitigated raw insert rate from this protected sample.

Given #4988716077 and #4989141674, this updated app/CLI datapoint may help separate two questions:

  1. whether the 0.145.x ChatGPT-integrated build has the target/callsite reductions expected from the 0.145 alpha line;
  2. whether the broader SQLite sink write/flush policy issue remains separate from the target filtering work.

A version-specific maintainer answer would still be useful: is 26.715.31925 / build 5551 / codex-cli 0.145.0-alpha.18 expected to be safe enough for affected users to remove local SQLite mitigations, or should users keep them until a stable desktop/CLI release with an explicit persistent-log fix ships?

TheJhyeFactor · 1 day ago

Hey, I had a look at this.

The SQLite sink already has a guard that drops bridged events with the log target before they reach the queue. The missing piece was a test that proves the guard still works when the outer tracing filter is permissive, which is the path that allowed this noise through in the first place.

I've added that regression test. It sends a bridged target="log" event alongside a normal Codex state event, flushes the sink, and checks that only the normal event was written to SQLite.

Branch: https://github.com/TheJhyeFactor/codex/tree/fix/sqlite-log-bridge-regression-29532

I ran CARGO_NET_OFFLINE=true cargo test -p codex-state locally on macOS. All 153 unit tests, 3 binary tests, and 1 doctest passed.

I couldn't open the PR because GitHub returned a CreatePullRequest permission error for my account, so I've linked the tested branch here for review.