Codex app-server persists high-frequency TRACE logs to logs_2.sqlite despite analytics/plugins disabled

Resolved 💬 3 comments Opened Jun 23, 2026 by yang200d Closed Aug 6, 2026
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What happened?

Codex Desktop app-server continuously persists high-frequency TRACE logs into ~/.codex/logs_2.sqlite.

This persists after:

  • setting user launch environment to lower verbosity:
  • RUST_LOG=warn
  • RUST_TRACE=0
  • CODEX_LOG=warn
  • adding this to ~/.codex/config.toml:
[analytics]
enabled = false
  • fully quitting and restarting Codex
  • temporarily disabling all plugins in ~/.codex/config.toml, then fully quitting and restarting Codex

This suggests the issue is likely in Codex app-server SQLite log persistence or log-level filtering, not an individual plugin.

Environment

  • Platform: macOS arm64
  • Codex Desktop app
  • Codex CLI version from codex doctor: 0.142.0
  • SQLite log DB: ~/.codex/logs_2.sqlite
  • SQLite journal mode: wal

Measurement method

I repeatedly measured a 60-second read-only window:

date
stat -f 'wal_size=%z wal_mtime=%Sm' ~/.codex/logs_2.sqlite-wal
sqlite3 -header -column 'file:~/.codex/logs_2.sqlite?mode=ro' \
  'SELECT MAX(id) AS max_id, COUNT(*) AS total_rows, datetime(MAX(ts), "unixepoch", "localtime") AS latest_log FROM logs;'

sleep 60

date
stat -f 'wal_size=%z wal_mtime=%Sm' ~/.codex/logs_2.sqlite-wal
sqlite3 -header -column 'file:~/.codex/logs_2.sqlite?mode=ro' '
  SELECT MAX(id) AS max_id, COUNT(*) AS total_rows, datetime(MAX(ts), "unixepoch", "localtime") AS latest_log FROM logs;
  SELECT level, COUNT(*) AS n, SUM(estimated_bytes) AS est_bytes
    FROM logs
   WHERE ts >= (SELECT MAX(ts)-60 FROM logs)
   GROUP BY level
   ORDER BY n DESC;
  SELECT datetime((ts/10)*10, "unixepoch", "localtime") AS ten_sec,
         COUNT(*) AS total,
         SUM(level="TRACE") AS trace
    FROM logs
   WHERE ts >= (SELECT MAX(ts)-60 FROM logs)
   GROUP BY (ts/10)
   ORDER BY (ts/10) DESC;
'

Results after [analytics] enabled = false

After fully quitting and restarting Codex:

BASELINE
local_now=2026-06-23 15:45:02 +0800
wal_size=13361192 wal_mtime=Jun 23 15:45:02 2026
max_id=2246189 total_rows=39233 latest_log=2026-06-23 15:45:02

AFTER_60S
local_now=2026-06-23 15:46:02 +0800
wal_size=13361192 wal_mtime=Jun 23 15:46:01 2026
max_id=2248212 total_rows=39233 latest_log=2026-06-23 15:46:00

TRACE 1168 estimated_bytes=1185916
INFO 5
DEBUG 3
WARN 2

10-second bucket peak:
2026-06-23 15:45:30 total=769 trace=762

Results after disabling all plugins

After temporarily disabling all plugins and fully restarting Codex:

BASELINE
local_now=2026-06-23 15:55:57 +0800
wal_size=13361192 wal_mtime=Jun 23 15:55:57 2026
max_id=2284701 total_rows=40252 latest_log=2026-06-23 15:55:57

AFTER_60S
local_now=2026-06-23 15:56:57 +0800
wal_size=13361192 wal_mtime=Jun 23 15:56:47 2026
max_id=2286987 total_rows=40252 latest_log=2026-06-23 15:56:46

TRACE 1438 estimated_bytes=1525478
DEBUG 8
INFO 5
WARN 2

10-second bucket peak:
2026-06-23 15:56:30 total=908 trace=903

TRACE targets after disabling all plugins

target                                    n    est_bytes
----------------------------------------  ---  ---------
log                                       972  105210
codex_api::sse::responses                 434  454233
codex_app_server::outgoing_message        38   6489
codex_mcp::connection_manager             32   26107
codex_api::endpoint::responses_websocket  3    1644287
codex_core::session::turn                 2    1822
codex_core::client                        2    1868

The active writer is the Codex app-server process itself, not an individual plugin process.

Related codex doctor findings

codex doctor --summary --no-color --ascii reported:

Codex Doctor v0.142.0 · macos-aarch64

[!!] websocket    Responses WebSocket failed; HTTPS fallback may still work
[XX] reachability one or more required provider endpoints are unreachable over HTTP
[--] app-server   not running (ephemeral mode)

The WebSocket warning may be relevant because persistent TRACE targets include:

  • codex_api::sse::responses
  • codex_api::endpoint::responses_websocket

Expected behavior

Codex Desktop should not continuously persist hundreds to thousands of TRACE rows per minute into ~/.codex/logs_2.sqlite, especially when analytics is disabled and all plugins are disabled.

Actual behavior

TRACE remains roughly 99% of recent log rows. Repeated 60-second windows show 1100-1400+ TRACE rows, and 10-second buckets can peak around 700-900+ TRACE rows.

Request

Please investigate whether Codex app-server is ignoring log-level filtering for SQLite persistence, especially for:

  • log
  • codex_api::sse::responses
  • codex_api::endpoint::responses_websocket
  • codex_app_server::outgoing_message

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 2 months ago

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

  • #29588
  • #29532
  • #29556
  • #29570
  • #29463

Powered by Codex Action

mdbecker · 2 months 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.

denispol · 2 months ago

The sink is independent of analytics/plugins, so disabling those doesn't stop it. Fix adds a real off-switch ([log] persist=false / CODEX_LOG_DB=off) and a configurable level: https://github.com/denispol/codex/pull/1