[macOS Desktop 26.721.41059] Persistent SQLite TRACE churn remains in bundled 0.146.0-alpha.3.1
What version of the Codex App are you using (From “About Codex” dialog)?
ChatGPT/Codex Desktop 26.721.41059 (build 5848), with bundled codex-cli 0.146.0-alpha.3.1.
What subscription do you have?
ChatGPT subscription. The exact tier does not appear relevant to this local app-server logging issue.
What platform is your computer?
Darwin 27.0.0 arm64 arm
macOS 27.0 (26A5378n), Apple Silicon.
What issue are you seeing?
The latest ChatGPT/Codex Desktop build available on this Mac still persisted high-frequency TRACE/DEBUG events to ~/.codex/logs_2.sqlite during ordinary active Codex use, producing measurable app-server disk writes and SQLite insert/prune churn.
Aggregate-only measurements collected before applying any workaround:
logs_2.sqlite: 380,895,232 byteslogs_2.sqlite-wal: 4,630,912 bytes- retained rows: approximately 30,000
sqlite_sequenceforlogs: approximately 30.23 millionPRAGMA page_count: 92,992PRAGMA freelist_count: approximately 80,000 (about 86% of pages)- a 50-second active sample advanced the sequence by 2,125 IDs, approximately 42.5 inserts/second
- a separate 30-second sample advanced it by 1,042 IDs, approximately 34.7 inserts/second
- in the latter sample, the bundled
codex app-serverwrote 14,462,976 bytes according to macOSproc_pid_rusage(RUSAGE_INFO_V4); the ChatGPT parent process wrote another 2,556,864 bytes - a more active 30-second window showed 43,909,120 bytes written by the app-server
The retained database was dominated by persistent diagnostic logging:
TRACE 16,484 rows ~26.01 MiB estimated
INFO 8,364 rows ~5.54 MiB estimated
DEBUG 5,477 rows ~4.30 MiB estimated
WARN 858 rows ~0.48 MiB estimated
ERROR 152 rows ~0.04 MiB estimated
The highest-volume current targets included:
codex_api::sse::responses TRACE
codex_app_server::outgoing_message TRACE
codex_mcp::connection_manager TRACE
codex_core::stream_events_utils DEBUG
codex_http_client::transport TRACE
This does not look like legacy file bloat alone. The high sequence value versus retained rows, the approximately 86% freelist, and the live sequence deltas show ongoing insert-and-prune churn. The process-level write counters confirm real disk writes, although those counters also include other app-server state files.
The current source still appears to configure the persistent SQLite layer with default_filter() whose default is LevelFilter::TRACE, plus a target denylist. RUST_LOG applies to the stderr formatting layer and does not provide a supported way to lower or disable the SQLite sink.
I did not inspect or attach raw feedback_log_body values because they may contain private task content, local paths, or identifiers.
What steps can reproduce the bug?
- Run ChatGPT/Codex Desktop 26.721.41059 on macOS with no insert-blocking trigger on the
logstable. - Start an active Codex task that streams responses and uses tools or subagents.
- In another terminal, record aggregate counters:
sqlite3 -readonly ~/.codex/logs_2.sqlite \
"SELECT (SELECT seq FROM sqlite_sequence WHERE name='logs'),
COUNT(*),
COALESCE(SUM(estimated_bytes), 0)
FROM logs;"
- Repeat after 30-60 seconds. The sequence advances by roughly 35-42 IDs/second in the observed active windows, while retained-row growth is much smaller because old rows are pruned.
- Inspect aggregate levels and targets:
sqlite3 -readonly ~/.codex/logs_2.sqlite \
"SELECT level, COUNT(*), SUM(estimated_bytes)
FROM logs GROUP BY level ORDER BY COUNT(*) DESC;"
- Confirm with
lsofthat the bundledcodex app-serverholdslogs_2.sqlite,-wal, and-shmopen for writing.
As an A/B confirmation, I later installed the community workaround:
CREATE TRIGGER block_log_inserts
BEFORE INSERT ON logs
BEGIN
SELECT RAISE(IGNORE);
END;
With the app reopened and actively used, four samples across 30 seconds then showed:
- sequence unchanged at 30,252,096
- retained row count unchanged at 32,393
- WAL unchanged at 8,272 bytes
- database and WAL modification times unchanged
This strongly isolates the persistent logs insert path as the source of the observed SQLite churn. The trigger is only a local stopgap and disables persistent diagnostics.
What is the expected behavior?
Normal production Desktop use should not persist per-event SSE, outgoing-message, networking, and tool-stream TRACE/DEBUG records to SQLite by default.
The persistent SQLite sink should:
- default to INFO or WARN rather than TRACE;
- provide a documented setting to disable or control persistent diagnostic logging;
- enforce a bounded DB/WAL byte budget and write-rate protection;
- avoid insert-then-delete churn for high-frequency events;
- provide a supported compaction/rotation command for existing bloated databases.
Additional information
Related reports:
- #28224 was closed as fixed, with a maintainer asking users who still see excessive writes to open a new bug report.
- #17320 remains open and documents the SQLite sink ignoring
RUST_LOG. - #30236 contains earlier Desktop reproductions, including bundled 0.146.0 alpha builds.
- #35092 documents residual per-SSE TRACE persistence in 0.145.0 and newer builds.
The earlier fixes substantially reduced the original catastrophic write rate, but this latest Desktop build still shows persistent TRACE-default policy and measurable write amplification. This report does not claim proven SSD failure or extrapolate the short active samples to a full year.
6 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Thanks — I reviewed both suggestions.
This report adds a controlled aggregate-only A/B on Desktop 26.721.41059 / bundled 0.146.0-alpha.3.1:
I opened a new report because the maintainer closing #28224 explicitly asked users who still observe excessive writes to provide a new bug report with details. I am happy for maintainers to deduplicate or close this in favor of #35092; the main value here is the latest exact Desktop build plus the before/after measurements.
Independent read-only reproduction on ChatGPT/Codex Desktop 26.721.41059 (build 5848), bundled
codex-cli 0.146.0-alpha.3.1, macOS 27.0 arm64.Aggregate measurements taken 2026-07-26 EDT, before applying any workaround:
~/.codex/logs_2.sqlite: 762,511,360 bytessqlite_sequenceforlogs: 85,873,999proc_pid_rusage(RUSAGE_INFO_V4)over the same interval recorded 8,253,440 bytes written by the bundled Codex process and 2,088,960 bytes by the ChatGPT parent (10,342,400 bytes combined); these counters include all process writes, not only this databasecodex_api::sse::responses | TRACE(134,744 rows; 145,410,632 estimated bytes)The rate in this window was lower than the samples in the issue body, but the unchanged retained-row count alongside the advancing sequence independently reproduces ongoing insert/prune churn on the same current Desktop build.
I did not inspect or attach raw
feedback_log_bodyvalues.Confirmed on another Apple Silicon Mac with the renamed ChatGPT app (bundle id
com.openai.codex), version 26.721.41059 / build 5848, macOS 27.0.Before mitigation,
~/.codex/logs_2.sqlitecontained 50,276 retained rows (26,040 TRACE; 12,475 DEBUG) and an estimated 58.38 MB of retained log payload. During a short active sample thesqlite_sequencevalue increased from 328,228 to 328,601: 373 inserts in roughly 30 seconds (~12.4/s).I applied the workaround described here:
Afterward, with the app still active, the sequence, row count, and estimated bytes remained unchanged (329,869 / 50,385 / 58,388,099) across a further sample. This cleanly stopped the SQLite insert churn locally. Normal Codex use continues, but persistent diagnostic logging is disabled, so this is only a mitigation—not a product fix.
PS: definitely less heat felt around my macbook air
I can corroborate this on Windows 10 22H2 (build 19045, x64) with a newer Codex Desktop package.
Environment:
26.727.6591.00.146.0-alpha.9.2mode=ro+PRAGMA query_only)Read-only sample:
MAX(id): 11,549,628 -> 11,549,934 (+306, about 84.7 IDs/minute)Levels among the 306 new retained rows:
Highest-volume targets:
codex_app_server::outgoing_message: 118codex_api::sse::responses: 85codex_core::stream_events_utils: 28feedback_tags: 22opentelemetry-otlp: 8Aggregate estimated persisted log bytes for those rows:
File observations:
logs_2.sqlite: 95,199,232 bytes -> unchangedlogs_2.sqlite-wal: 3,530,872 -> 4,173,592 bytes (+642,720 bytes)logs_2.sqlite-shm: 32,768 bytes -> unchangedlogs_2.sqlite-walandstate_5.sqlite-wal; the instantaneous values are not used as the primary measurement hereThis reproduces the same insert-and-prune churn on Windows: the base DB and retained row count can remain flat while IDs advance and the WAL keeps changing. The current dominant targets are per-message/per-SSE tracing rather than the older bridged
target=lognoise.I am not claiming proven SSD damage or attributing an audible mechanical-disk sound to this SQLite activity; the Codex state directory in this reproduction is on an SSD. The actionable issue is avoidable persistent TRACE write amplification and the lack of a documented, supported control for the SQLite log sink.
Requested direction:
codex_api::sse::responsesandcodex_app_server::outgoing_messageTRACE events before SQLite insertion;Follow-up reproduction on a newer macOS Desktop build, after the SQLite logging mitigations shipped through the 0.148/0.149 line.
Environment:
26.818.31338(build6892)codex-cli 0.149.0-alpha.4Controlled A/B method:
BEFORE INSERT ON logs ... RAISE(IGNORE)mitigation trigger was active.PRAGMA wal_checkpoint(TRUNCATE).Results with the trigger temporarily disabled:
TRACE targets in that batch:
After restoring the trigger and truncating the WAL, a further 15-second active sample showed:
MAX(id)unchanged at 42,767,635This suggests the newer build has changed the write shape from frequent small commits to a roughly 8-second batch in this short sample, but it has not eliminated persistent TRACE/WAL activity. The dominant residual source here is now
codex_app_server::outgoing_message, rather than the HTTP/SSE/WebSocket targets addressed by recent filtering changes.This appears consistent with the broader root-cause discussion in #31542, while adding a post-0.148/0.149 macOS data point. A supported persistent-SQLite log-level/disable control, or filtering/sampling
codex_app_server::outgoing_messagebefore insertion, would avoid requiring an unsupported schema trigger.I am not extrapolating this short active sample to annual SSD wear; the actionable observation is that the SQLite sink still performs avoidable TRACE persistence and WAL writes during normal active use.