Skip to content

Severe CLI reliability failure: 63.8 MB image-history requests before any compaction, WebSocket fallback, and prolonged stalls on Windows #43015

Open

Description

@FengYeeLx

Summary and urgent request

Please urgently investigate aggregate image-history byte growth and the repeated full-request cost after WebSocket fallback, and provide a supported recovery path for affected sessions.

In a real image-assisted coding task, Codex accumulated 63,759,837 bytes per request, still 45,853,691 bytes after zstd compression. At the corresponding history snapshot, 38 typed image occurrences accounted for 61,279,872 ASCII data-URL characters. This happened before any compaction, not only through images retained in an old compacted replacement history.

The failure had a serious practical impact: repeated stream errors, five-attempt retry batches, HTTPS fallback, and prolonged periods in which the primary task did not advance. One failed sequence on 0.153.2 lasted approximately 88 minutes without new effective model output. Updating to 0.153.4, the latest stable release when checked on September 5, did not remove the accumulated payload or prevent the observed WebSocket fallback.

I am extremely dissatisfied with this experience. These failure periods made Codex CLI effectively unusable for my paid development workflow. Waiting through prolonged retries without an actionable explanation or reliable recovery procedure is unacceptable. Users should not need to inspect SQLite databases, count Base64 payloads, or study client source code merely to keep an image-assisted coding task usable. I am asking for urgent maintainer triage, a supported mitigation, and a prioritized fix—not merely another generic reconnect warning.

The report also includes a later partial recovery: a successful compaction removed the old tool-image payloads from active replacement history and work resumed. I am not claiming permanent data loss or that every use of view_image fails.

Related reports and the additional evidence here

This is closely related to #41338 and #24550. Please consolidate this evidence into an existing tracker if that is the preferred triage path.

The distinguishing measurements are:

  • Windows, the built-in OpenAI provider, ChatGPT authentication, and current stable 0.153.4—not a Responses-to-Chat bridge.
  • Zero compaction records at the failure snapshot: ordinary current-window image outputs can already create the large-request condition.
  • 37 distinct data URLs across 38 occurrences. Exact deduplication would remove only 1,119,846 bytes, or 1.83% of the image data.
  • The largest individual data URL was 5,183,170 bytes. None exceeded 10 MiB. A per-image 10 MiB ceiling alone would not address this workload.
  • Actual pre/post-compression request measurements, separately from rollout file size and token accounting.
  • A subsequent compaction that can be inspected structurally: tool-output images were removed, while the original user-message images remained.

Environment

Field Observed value
Codex CLI 0.153.2 during the original long failed sequence; upgraded to 0.153.4 before the later resumed failure
Current stable release checked rust-v0.153.4, published September 4, 2026
Source version audited 3d2ee51ca2d5db578f328aa75e20aa22c0197c9a / rust-v0.153.4
Platform Windows x64, OS build 10.0.26100
Shell PowerShell 7.6; terminal-emulator version not collected
Subscription / authentication ChatGPT Pro; ChatGPT authentication
Provider Built-in OpenAI provider, Codex Responses endpoint
Model gpt-6-astra
Reasoning selection Initially xhigh; the resumed pre-compaction and post-compaction turns both used ultra
Service tier default
Network Explicit HTTP/HTTPS proxy variables pointing to a local v2rayN proxy; TUN/routing changes are disclosed below

Relevant non-default context settings were:

model_context_window = 1000000
model_auto_compact_token_limit = 900000

The session reported a model_context_window of 828,400. I am disclosing the configured values without asserting that they were the effective runtime limits. This is not a claim of reproduction with an untouched default configuration. It is a supported long-context workflow that lacked an effective safeguard against its much larger serialized image payload.

Codex doctor report

A new full codex doctor --json report was not collected for this investigation. The evidence below comes from targeted read-only inspection of the affected rollout, retained client logs, process/network state, and the pinned client source. I am not substituting an older doctor report or claiming that doctor passed.

What happened: measured request and history sizes

The HTTP client recorded the following at 2026-09-05 11:12:14 UTC:

Compressed request body with zstd
pre_compression_bytes=63759837
post_compression_bytes=45853691
compression_duration_ms=78

Several earlier requests in the same resumed task were almost as large:

UTC Before compression After compression Compression time
10:55:20 63,721,050 B 45,827,415 B 70 ms
10:57:42 63,740,637 B 45,841,192 B 76 ms
10:58:22 63,742,371 B 45,842,100 B 70 ms
10:59:43 63,742,371 B 45,842,094 B 98 ms
11:12:14 63,759,837 B 45,853,691 B 78 ms

These are application-recorded request-body sizes, not inferred wire traffic, billing totals, or the size of the JSONL file. Compression itself was fast; the measurements do not justify blaming local zstd work for multi-minute delays.

The corresponding history was inspected through 11:12:15 UTC, counting only response_item records:

Typed image location Occurrences Data-URL characters / ASCII bytes
User-message content[].image_url 7 4,307,974
Function/custom-tool output[].image_url 31 56,971,898
Total 38 61,279,872

All counted image values belonged to typed input_image objects. UI/event duplicates were not included in these totals. The main sources were generated images and image-viewing tool outputs; this is not a claim that the whole total came from view_image alone.

The last completed request recorded at 10:58:22 UTC reported 482,479 input tokens, of which 480,000 were cached. That is the last completed-request usage record, not a new usage measurement for the 11:12 submission. It demonstrates that high token-cache reuse coexisted with repeated large requests; unchanged usage counters do not prove the backend performed no work or incurred no cost.

Failure chronology and severity

All times below are September 5, 2026, UTC.

Time / interval Observation
08:53:15–10:21:18, CLI 0.153.2 After the last productive tool result, repeated response-stream failures produced no new effective model output for approximately 88 minutes; the turn eventually failed.
09:08:19, 09:23:24, 09:38:29, 09:51:07, 10:06:11 Five recorded retries in that failed sequence. The roughly 15-minute spacing is observed behavior, not a claim about a proven timeout setting.
10:51–10:52 CLI upgraded to 0.153.4 and restarted; the original session was resumed.
10:53 Multiple WebSocket handshakes succeeded; actual request sends then failed with Windows error 10054 and exhausted five retries.
10:54:01 HTTP fallback was activated.
10:55–10:58 Some productive tool activity resumed, including starting two subagents.
10:59:43 A separate manual route change restarted the proxy and caused a known disconnect. This event is treated separately, as explained below.
11:00:19 and 11:12:44 HTTPS requests received HTTP 200; SSE keepalives were also observed during long waits.
11:07:35 and 11:08:44 The two subagents completed; their progress must not be confused with the primary thread's progress.
11:31:23–11:36:38 The running turn was interrupted, then a compaction ran and completed.

The errors included:

stream disconnected before completion:
failed to send websocket request: IO error: ... (os error 10054)

Falling back from WebSockets to HTTPS transport

stream disconnected before completion:
Transport error: network error: error decoding response body

The original 88-minute terminal failure occurred on 0.153.2. The later handshake/send failures, fallback and large requests were observed on 0.153.4. I am not attributing the earlier 88-minute sequence to the newer binary.

Later recovery: important evidence, not omitted

At 11:36:38, the completed compaction installed a replacement history containing:

  • 36 items: 35 messages and one compaction item;
  • 7 embedded images totaling 4,307,974 characters;
  • approximately 4,378,186 bytes when serialized as compact UTF-8 JSON by the inspection code.

The retained image multiset exactly matched the earlier user-message image multiset. The old raw tool outputs were no longer present in the replacement history. Relative to the earlier snapshot, embedded image bytes decreased by approximately 92.97%.

Subsequent retained HTTP logs showed requests around 9.8–10.9 MB before compression, substantially below the earlier 63.8 MB, and the primary thread again performed commands and file edits. Those later requests already included additional post-compaction work, so they are not the size of the first untouched compacted request.

This is a natural before/after observation, not a controlled benchmark. The model selection remained Astra/Ultra and the same CLI process continued, but the workload changed and upstream conditions were not controlled. Long waits were not eliminated: one later parent-thread tool-result-to-next-tool-call interval was still about 11 minutes.

The observed recovery supports treating active-history size as an important contributor. It does not prove that compaction alone fixes every affected thread, or that every minute of delay was upload time. It also matches an important implementation distinction: current compaction can discard original tool outputs while retaining user images.

Reproduction conditions

The observed workload was:

  1. Run a long image-assisted coding session using the built-in OpenAI provider and the environment described above.
  2. Generate and inspect multiple images through normal tools. Retain several dozen prepared images in active history; individual images need not exceed 10 MiB.
  3. Continue model/tool iterations without a compaction having reduced that history.
  4. Resume the same history after a CLI restart.
  5. Compare request-body byte measurements with token accounting, and observe whether the actual resumed WebSocket request succeeds after the handshake.

This describes the real failure conditions. A standalone minimal deterministic network reproducer and a sanitized-copy A/B test have not been run. The private workload cannot be pasted into a public issue. The report is not evidence that every image, network, model, or default configuration reproduces the transport failure.

Technical assessment: what is proven, and what is most likely

Confirmed: this workload retained tens of megabytes of typed image data and repeatedly constructed very large requests. The current source explains how that payload survives truncation and is resent when the full-history path is used.

Most strongly supported explanation of the amplification: accumulated inline images become expensive repeatedly when incremental WebSocket continuation is unavailable and the client submits the full active prompt over HTTP. Additional images can enlarge subsequent submissions again. The natural compaction observation and related community controls support this explanation.

Not established: the exact origin of the first TCP reset, a particular server/proxy message-size ceiling, or a universal causal relationship between image size and every observed stall. Payload size or multimodal replay shape may trigger a transport/endpoint limitation, but local/upstream proxy behavior and backend processing are still possible contributors. High reasoning effort also contributes to ordinary model latency.

Pinned source evidence and the conditional byte-amplification argument

The following code was checked at release commit 3d2ee51ca2d5db578f328aa75e20aa22c0197c9a:

Component Relevant behavior
Image-viewing handler Produces a data URL and a typed image output. Omitting the image from the log preview does not remove it from model input.
Tool-output truncation Text is budgeted/truncated while InputImage URLs are copied in the inspected paths.
History/token estimation Replaces the actual Base64 byte contribution with an image-token estimate. Correct token estimation still requires a separate serialized-byte safeguard.
Request construction and transports HTTP constructs a request from the formatted active prompt. WS may use incremental input when prior-response state and prefix matching permit it; otherwise it uses full input.
Compacted-history retention Filters ordinary raw tool outputs; retained user images can remain. Thus compaction outcomes depend on the history's shape.
WebSocket response stream The ordinary Message::Close(_) branch discards close details and returns a generic stream error. This does not imply that our 10054 included a close frame.

The deterministic part can be stated narrowly. Let b_i be the byte length of each prepared inline image URL retained in a history that is serialized in full. These strings must contribute at least sum(b_i) bytes to that uncompressed request, before surrounding JSON and other inputs. If the same image strings are retained across k such requests, they contribute at least k * sum(b_i) bytes across the constructed request bodies.

That is a serialization consequence under stated conditions. It is not proof that all requests reach the network in full, that those bytes are billable tokens, or that a connection must fail at a particular size. Compression and WS incremental continuation change transfer costs; the recorded zstd sizes establish the substantial cost in this case.

For this workload, a single-image ceiling and exact deduplication are insufficient on their own: no image exceeded 10 MiB, and 37 of 38 encoded images were distinct. The safeguard needs an aggregate/lifecycle dimension.

Confounders and limits explicitly checked

  • Proxy route change: at 10:59:43, changing routing restarted Xray/sing-box and disrupted both the affected session and another active session. That disconnect is not used as proof of image-induced failure. Earlier failures predated it.
  • Proxy configuration was present: explicit HTTP/HTTPS proxy settings were active and actual WebSocket handshakes succeeded. This differs from an older missing-proxy/handshake-timeout problem.
  • Connection versus progress: HTTP 200 and periodic SSE keepalives demonstrate some established stream activity, not completion of model work. I am not calling every long wait a deadlock.
  • Local resource evidence: the inspected snapshots did not show CPU/memory exhaustion; local request compression was measured in milliseconds. These snapshots do not exclude every possible local bottleneck.
  • Billing: no monetary loss, duplicate model billing, or precise quota waste is claimed from the byte counts or unchanged usage counters.
  • Recovery: a compaction later succeeded and work resumed. No permanent data loss or permanently unrecoverable session is claimed.
  • Log retention: older retained-client-log rows rotated during the investigation. Their measurements were captured while present; the persistent rollout and saved diagnostic observations were cross-checked. No unrestricted packet capture or server-side trace was obtained.

Existing fixes and reports have been considered

Reference Relevance and boundary
#41338 Directly reports the byte/token mismatch from local image viewing; open when checked.
#24550 Reports WS retries/fallback with retained images. Its original compaction-specific reproduction differs from this pre-compaction case.
#30441 Related image-history size failures; this local report does not claim a 413 was observed.
#24388 and closure response Acknowledges an earlier compaction issue and explains a change in compaction implementation. This should not be read as confirmation that every image-byte retention problem is fixed.
Merged PR #38681 Preserves parent HTTP fallback for delegated sessions. Its commit is an ancestor of 0.153.4 and the relevant code is present. I am not claiming that this specific fix is absent.

In particular, I am not requesting that maintainers redo #38681. Please assess the remaining current-window byte growth and repeated full-history submission separately from already-addressed delegated-session fallback behavior.

Expected behavior and urgent requested action

Image viewing is a core, legitimate workflow. The expected solution should preserve useful visual capability rather than requiring users to avoid images altogether.

Please:

  1. Urgently triage and assign ownership for the aggregate image-history/request-byte problem, clarify which existing tracker owns it, and provide a current supported mitigation and expected fix/release path.
  2. Add an aggregate serialized-byte safeguard, independent of token budgeting, covering ordinary tool outputs before compaction as well as continuation, resume/fork and compacted history. Many individually small images must be covered.
  3. Provide a bounded lifecycle or out-of-band representation for older image artifacts, with explicit references and on-demand retrieval. Do not silently discard task-critical current images or the user's original files.
  4. Avoid repeatedly resubmitting a deterministically rejected large request unchanged. Preserve actionable close/status details when available; do not infer an oversize error solely from a generic TCP reset.
  5. Provide a supported recovery procedure for existing affected sessions, with preservation of project files and useful task context, instead of requiring manual JSONL/SQLite surgery or abandoning a long task without a reliable handoff.
  6. Make the UI distinguish connection attempts, accepted requests with heartbeats, actual model progress, and repeated request-size failure. Surface the relevant byte measurements and a useful recovery action.

Suggested regression coverage should include multiple sub-10-MiB images, current-window tool images before any compaction, high token-cache reuse with large serialized bodies, both user and tool images after compaction, and repeated continuation after fallback. Please verify both the request bytes and successful follow-up behavior; a low token count or a successful compaction notification alone is insufficient.

This is a serious interruption to paid, real development work, not a cosmetic warning. Please provide an actionable official response as soon as possible.

Privacy and supporting material

Only sanitized measurements and code references are included. Raw rollouts, images, prompts, project paths, credentials, cookies, account identifiers and private request IDs are intentionally omitted. Please specify an appropriate secure channel if additional private diagnostic material is necessary for triage.

Activity

  1. added
    bugSomething isn't working
    CLIIssues related to the Codex CLI
    windows-osIssues related to Codex on Windows systems
    connectivityIssues involving networking or endpoint connectivity problems (disconnections)
    contextIssues related to context management (including compaction)
    on Sep 5, 2026
  2. FengYeeLx commented on Sep 6, 2026

    @FengYeeLx
    Author

    @kchainani-oai — apologies for the direct ping. I am mentioning you because you have very recently worked on Codex's core image-preparation path.

    I would appreciate triage or routing to the current owner of image history / request construction. This report appears to expose a boundary that the existing retained-image compaction safeguards do not cover: aggregate serialized image growth in ordinary active history before any compaction has occurred.

    The measured affected request reached:

    • 63,759,837 bytes before compression;
    • 45,853,691 bytes after zstd;
    • 61,279,872 data-URL characters across 38 typed image occurrences;
    • 37 distinct data URLs across those 38 occurrences;
    • largest individual data URL: 5,183,170 bytes;
    • no individual image above 10 MiB;
    • zero compaction records at the measured failure snapshot.

    Exact deduplication would recover only about 1.83% of the image data in this workload. A single-image 10 MiB ceiling would also not prevent it.

    The later successful compaction naturally reduced embedded image bytes by about 92.97% and productive work resumed, which further supports active-history size as an important contributor, while not proving that every observed transport stall was caused by payload size.

    The key architectural concern is therefore not merely retained images after compaction. It is that model-token/context budgeting and actual serialized-request-byte growth can diverge substantially during a normal multimodal working window.

    A new codex doctor --json diagnostic was also collected in #43168. It reports the active ChatGPT provider endpoints as reachable and the Responses WebSocket handshake as successful.

    Additional internal diagnostics were uploaded through /feedback:

    01a0755c-377e-75a1-9085-6f6a34bda5cf

    Could you please triage this or route it to the current owner of image preparation/history/request serialization? I am especially looking for a supported short-term mitigation and whether an aggregate active-history byte budget is already planned.

    Related reports: #41338 and #24550.

    Please help. @kchainani-oai

  3. FengYeeLx commented on Sep 7, 2026

    @FengYeeLx
    Author

    Status update — 2026-09-07

    I re-checked current main for changes relevant to this report.

    There is now a potentially relevant under-development feature, UnifiedImageBudget. Its source description is:

    Apply one shared pixel and token budget to every image, regardless of legacy detail hints.

    It is currently marked UnderDevelopment and default_enabled: false, and the image-preparation path supports ImagePreparationMode::UnifiedBudget.

    This looks relevant and may materially reduce individual prepared image sizes. However, I cannot tell from the current implementation whether it is intended to solve the specific failure boundary demonstrated in this issue: aggregate serialized-byte growth across many images in ordinary active history.

    That distinction matters here because the measured workload had:

    • 38 typed image occurrences;
    • 37 distinct data URLs;
    • 61,279,872 total data-URL characters;
    • no individual image above 10 MiB;
    • largest individual image only 5,183,170 bytes;
    • zero compactions at the measured failure snapshot.

    So a per-image pixel/token policy may mitigate the magnitude, but it does not obviously provide a bounded aggregate serialized-request byte budget as the number of retained images grows.

    There is also independent evidence in #41338 showing the same broader byte-vs-token asymmetry on macOS: one reported compacted history retained 23 complete PNG data URLs totaling 57,737,086 characters, producing a request of approximately 58.85 MB before zstd / 28.80 MB after zstd, with substantially worse time-to-first-reasoning than a fresh thread.

    That cross-platform evidence makes this look less like a Windows-specific transport artifact and more like a general lifecycle/request-construction problem around inline image history.

    Could a maintainer clarify whether UnifiedImageBudget is intended to cover the aggregate serialized-history/request-byte problem reported here?

    If it is not, I believe this issue still requires a separate aggregate/lifecycle safeguard — for example a serialized-byte budget, eviction/replacement policy, or out-of-band image representation — in addition to per-image preparation limits.

    Latest stable remains 0.153.4.

  4. FengYeeLx commented on Sep 8, 2026

    @FengYeeLx
    Author

    Follow-up — September 8, 2026

    Hi @kchainani-oai — my apologies for one further mention, and thank you for your time.

    Could you please help route this report to the appropriate owner of image-history retention or request construction? I appreciate that the report is recent. My immediate hope is to understand the supported mitigation and whether existing work already covers this failure boundary.

    Following up on my September 7 note, the distinction I would particularly appreciate clarification on is aggregate serialized image bytes across active history, rather than only the preparation limits applied to each individual image.

    The measured request was 63,759,837 bytes before compression and 45,853,691 bytes after zstd. The corresponding history contained 38 typed image occurrences with 37 distinct data URLs, before any compaction had occurred. No individual image exceeded 10 MiB. The original report also discloses the non-default context settings; I am not presenting this as an all-default-configuration reproduction.

    At main commit 3caf9f9586baedb4158a7b91545ead3dd320c348, UnifiedImageBudget remains under development and disabled by default. The inspected preparation path processes images individually. I am therefore not treating it as a confirmed aggregate-byte mitigation or assuming that it necessarily reduces every image's serialized size.

    Is that feature intended to address the aggregate active-history/request-size problem, or does this need separate handling elsewhere? Guidance on a supported recovery path for already affected ChatGPT-authenticated sessions, without manually editing session files, would be especially helpful.

    The associated diagnostic reference is recorded in #43168:
    01a0755c-377e-75a1-9085-6f6a34bda5cf

    I would be happy to consolidate the evidence under #41338, #24550, or another tracker you recommend. Even a brief routing acknowledgment would help me avoid duplicating work or following the wrong mitigation.

    Thank you again for your time and consideration.

  5. NayaCcR commented on Sep 8, 2026

    @NayaCcR

    Same issue here. Looking forward to a fix.@jif-oai @kchainani-oai

  6. FengYeeLx commented on Sep 8, 2026

    @FengYeeLx
    Author

    @etraut-openai @bc-openai @riley-oai @rhan-oai @fcoury-oai @fchen-oai @felixxia-oai @jif-oai

    I am deeply sorry for tagging so many of you at once.

    I know this is intrusive, and I know that mass-mentioning maintainers is generally not an appropriate way to ask for help. I genuinely apologize for adding another notification to your workload. I would not do this under normal circumstances, and I do not intend to make a habit of it.

    I am doing it only because I have run out of reasonable ways to determine how to get these two reports in front of the right person:

    I have tried very hard to make both reports useful rather than simply reporting that “Codex is broken.” They include sanitized evidence, reproduction conditions, measurements, source-level observations, explicit limits on what the evidence does and does not prove, and suggested areas to investigate.

    I also submitted an internal /feedback diagnostic bundle and created #43168 solely so that the diagnostic thread could be associated with the two canonical reports.

    I understand that the Codex repository receives an extraordinary number of issues, that everyone here has their own responsibilities, and that many of you may have nothing to do with these particular components. I am not asking everyone I tagged to investigate the bugs, and I am absolutely not asking for an immediate fix or a release commitment.

    I am asking for something much smaller:

    If even one person here knows which engineer/team owns the relevant code, could you please help route these reports to them, or leave a brief indication of where I should take them?

    Even something as short as:

    “This belongs to X; please continue there.”

    or:

    “The team is aware of this; no additional reports are needed.”

    would be enormously helpful.

    For #43022 in particular, I have tried to reduce the problem to a deterministic local transport experiment so that investigation does not depend on reproducing an intermittent production stall.

    For #43015, I have tried to separate model-token accounting from aggregate serialized request size and to provide concrete byte measurements rather than speculation.

    I am completely willing to provide additional sanitized diagnostics, run a narrowly specified experiment, test a candidate build, or correct anything in my analysis if I have misunderstood the implementation.

    And if this mass mention itself is inappropriate, I sincerely apologize. Please feel completely free not to respond individually. I only need one route to the correct owner.

    I care about Codex a great deal and use it heavily in real development work. My persistence here is not intended as criticism of any individual engineer. It comes from these failures having become serious workflow blockers for me, while I have been unable to determine any other reliable escalation path.

    Again, I am very sorry for the broad notification, and I appreciate anyone who took the time even to read this far.

    Thank you very much for your time, and please accept my apologies for the interruption.

  7. FengYeeLx commented on Sep 8, 2026

    @FengYeeLx
    Author

    Follow-up: consolidated related-issue map across the full inline-image / history / compaction lifecycle

    I am adding one final consolidated cross-reference map because there is now a substantial set of independent Codex reports covering inline image/media payloads at different stages of the history lifecycle.

    I am not asserting that every issue below is a duplicate of #43015 or that every image-related stall has one identical root cause.

    The important distinguishing evidence in #43015 remains:

    • request body measured at 63,759,837 bytes before zstd;
    • 45,853,691 bytes after zstd;
    • 38 typed image occurrences;
    • 37 distinct data URLs;
    • 61,279,872 total image data-URL characters;
    • largest individual data URL approximately 5.18 MB;
    • no individual image exceeded 10 MiB;
    • exact deduplication would save only approximately 1.83%;
    • most importantly, the relevant failure snapshot contained zero compaction records.

    Therefore this issue is specifically evidence that ordinary active history can already become pathologically large before compaction has occurred.

    For clarity, the lifecycle can be divided into:

    Stage A
    image preparation / individual image handling
    
    Stage B
    ordinary active model history before successful compaction
    
    Stage C
    compacted / retained / persisted / forked history
    

    #43015 primarily demonstrates the missing Stage-B aggregate serialized-byte safeguard.


    1. Strongest direct byte-vs-token and active-request corroboration

    These reports span different surfaces/providers and should not be mechanically merged, but they independently establish that serialized request bytes matter in ways that token counts alone do not capture.


    2. Image-heavy sessions becoming slow, stuck, or repeatedly reconnecting

    These issues are less direct about the exact request-byte threshold, but independently show the same workload class becoming unreliable after image history accumulates.

    These are useful impact/corroboration reports, but I am not using them as proof of the exact 63.8 MB causal chain in #43015.


    3. Failed-compaction / poisoned-session recovery


    4. Compaction retaining or duplicating raw image/media payloads

    These primarily concern Stage C rather than the zero-compaction Stage-B condition demonstrated in #43015.

    They are nevertheless important because they show that the same representation problem continues after compaction unless explicitly bounded.

    The existence of Stage-C mitigations does not eliminate the Stage-B problem.

    A session may accumulate tens of megabytes of active image history before the first successful compaction, as #43015 demonstrates.


    5. Fork / resume / subagent amplification

    Once heavyweight inline history exists, several independent reports show that resume/fork/subagent paths can multiply or reconstruct it.

    The key architectural point is that incremental continuation can temporarily hide the cost of a large history. A reconnect, resume, reuse mismatch, fork, or HTTP fallback can then require a full-history request and suddenly expose the serialized-byte problem.


    6. Additional linked persistence / compaction / storage reports

    The closest reports above themselves reference a wider family of related issues.

    For completeness, those secondary references include:

    I am listing these as secondary related references only. They should not be assumed to reproduce the specific Stage-B 63.8 MB condition in #43015.


    7. Adjacent context-accounting issues

    These are supporting context-management references rather than direct request-size reproductions.


    8. Separate but interacting WebSocket-liveness issue

    This is deliberately a separate issue.

    Its deterministic localhost reproduction is image-free and only approximately 42 KB, so large image history is not necessary to reproduce the #43022 liveness bug.

    However, the two classes of defect can plausibly amplify each other in production:

    large active inline-image history
            ↓
    large full request / expensive request ingestion
            ↓
    longer application-event silence or transport failure
            ↓
    retry / reconnect / HTTP fallback
            ↓
    full history may need to be constructed and submitted again
            ↓
    additional latency and repeated payload cost
    

    This is a system-level amplification model, not a claim that every observed timeout followed this exact chain.


    9. Diagnostic bridge

    This can be correlated with the separately supplied diagnostic material if useful.


    Why a per-image limit or token-only compaction is not sufficient

    The measured #43015 history contained:

    38 image occurrences
    37 distinct data URLs
    61,279,872 total data-URL characters
    largest individual image URL ≈ 5.18 MB
    no image > 10 MiB
    exact deduplication benefit ≈ 1.83%
    

    Therefore:

    per-image bound != aggregate history bound
    token budget != serialized-byte budget
    

    A workload containing many individually acceptable images can still produce a pathological aggregate request.

    The relevant invariant needs to cover the whole active model-visible history, not only each image independently and not only retained images after compaction.

    Conceptually:

    token/context constraint:
        T <= T_max
    
    serialized active-history/request constraint:
        B <= B_max
    

    The exact value and policy for B_max is an implementation/product decision, but some aggregate byte-denominated lifecycle invariant is needed if downstream transports/endpoints have byte-denominated limits or pathological processing costs.


    Requested maintainer action

    I would appreciate triage specifically across the entire lifecycle rather than treating this only as a compaction-retention issue.

    In particular:

    1. Add an aggregate serialized-byte safeguard for ordinary active history before compaction.
    2. Apply the safeguard across:
      • normal continuation;
      • WebSocket full-history reconstruction;
      • HTTP fallback;
      • resume;
      • fork;
      • subagent inheritance;
      • compaction input;
      • compacted retained history.
    3. Keep individual-image preparation limits, but do not rely on a per-image ceiling alone.
    4. Avoid retrying an unchanged request that is already known to exceed a transport/request constraint.
    5. Preserve useful image capability instead of requiring users to avoid image workflows.
    6. Externalize or lifecycle-manage older binary artifacts where appropriate rather than indefinitely replaying Base64.
    7. Provide a supported repair/recovery path for already affected threads without manual JSONL/SQLite surgery.
    8. Expose actionable diagnostics such as:
      • aggregate serialized request bytes;
      • image count / image bytes;
      • whether the request is incremental or full-history;
      • whether compaction is being attempted;
      • the actual transport/server rejection reason when available.
    9. Identify the release containing the eventual fix once known.

    The purpose of this comment is to make the existing independent evidence discoverable in one place while preserving the evidence boundaries of each report.

    The central additional result from #43015 is still the zero-compaction observation:

    the active history itself reached approximately 63.8 MB before any compaction existed to reduce it.

    That is why Stage-B aggregate byte management appears to remain a necessary part of the fix, even if later compaction/image-budget paths are also improved.

  8. FengYeeLx commented on Sep 8, 2026

    @FengYeeLx
    Author

    Source-level clarification: model-context accounting and serialized-request bytes are separate resource dimensions

    I found one additional source-level detail on current main that appears to make the architectural boundary in this report more precise.

    This is not a new runtime reproduction, and it does not change the evidence boundaries in the original report. In particular, I am not claiming a universal server-side request-size limit, nor that every transport stall observed in the affected session was caused by payload size.

    The new point is narrower:

    Codex's current context estimator intentionally discounts the actual Base64 byte length of inline images and replaces it with a model-oriented image cost estimate. That appears reasonable for estimating model context usage, but it means model-context budgeting cannot, by construction, impose an aggregate bound on the actual serialized request body.

    That distinction appears directly relevant to the zero-compaction, 63.8 MB active-history condition measured in this issue.


    1. Current history accounting explicitly separates image payload bytes from model-visible cost

    Checked on current main commit:

    ce254df05a3162a93d8f3357ff4dd86582c534b7

    Relevant source:

    https://github.com/openai/codex/blob/ce254df05a3162a93d8f3357ff4dd86582c534b7/codex-rs/core/src/context_manager/history.rs

    In estimate_response_item_model_visible_bytes, Codex first obtains the serialized JSON size of an item, but then separately measures inline image payloads and replaces their actual Base64 payload contribution with a modality-specific estimate.

    The core operation is effectively:

    let raw = serialized_json_bytes(item);
    
    let (image_payload_bytes, image_replacement_bytes) =
        image_data_url_estimate_adjustment(item);
    
    let raw = raw
        .saturating_sub(image_payload_bytes)
        .saturating_add(image_replacement_bytes);

    The source comment explicitly describes this as replacing raw Base64 payload bytes with per-modality estimates.

    For ordinary resized image inputs, the current estimator uses:

    const RESIZED_IMAGE_BYTES_ESTIMATE: i64 = 7373;

    and later converts the estimated model-visible byte count to an approximate token count.

    For detail: "original", the estimator instead decodes the image dimensions and estimates the model-visible cost from 32 px patches, capped at 10,000 patches.

    The important point is that this is not necessarily incorrect token accounting.

    For model context purposes, a multi-megabyte PNG should not necessarily cost the model the same number of tokens as several megabytes of ordinary text. The model sees an image modality, not a Base64 character stream in the ordinary text-token sense.

    The problem exposed by this issue is therefore a different resource constraint.

    There are at least two independent quantities:

    T_model
        model-visible context / token cost
    
    B_serialized
        actual serialized request-body bytes
    

    A request can satisfy:

    T_model <= T_budget
    

    while B_serialized continues growing independently to an operationally problematic size.

    That is exactly the kind of divergence observed here.


    2. Why this matters for the measured #43015 workload

    The affected history measured in this report contained:

    • 38 typed image occurrences;
    • 37 distinct image data URLs;
    • 61,279,872 image data-URL characters;
    • largest individual image data URL: 5,183,170 bytes;
    • no individual image above 10 MiB;
    • only approximately 1.83% possible savings from exact deduplication;
    • zero compaction records at the measured failure snapshot.

    The HTTP request layer recorded:

    pre_compression_bytes=63759837
    post_compression_bytes=45853691
    

    The important observation is therefore not merely:

    "the token counter underestimated the prompt."

    A more precise statement appears to be:

    the model-context estimator and the transport/request-body size are measuring intentionally different resources, but only the former participates in the normal context lifecycle strongly enough to trigger reduction before the latter becomes very large.

    For this workload, the active history could therefore remain acceptable under the model-context accounting while containing more than 60 MB of serialized inline image data.

    This also explains why prompt caching does not eliminate the problem.

    Caching may reduce repeated model computation associated with unchanged context, but it does not by itself remove the inline Base64 strings from a full serialized request when that request must be reconstructed and submitted again.


    3. The missing invariant appears to be aggregate and byte-denominated

    The architectural safeguard I am asking about is therefore not:

    count Base64 bytes as ordinary text tokens
    

    and not merely:

    improve the image token estimate
    

    Instead, there appears to be a missing independent invariant for the model-visible active history.

    Conceptually:

    T_model <= T_budget
    AND
    B_serialized <= B_budget
    

    where B_budget is an implementation-defined operational budget, not a server limit that I am claiming to know.

    The byte budget also does not necessarily need to mean "hard reject the user request."

    It could instead be a preflight trigger for one or more lifecycle actions before constructing or retrying an excessively large full-history request, for example:

    aggregate byte budget exceeded
            |
            +--> compact history if possible
            |
            +--> evict or replace older media
            |
            +--> externalize binary artifacts and retain stable references
            |
            +--> reduce redundant retained tool-image outputs
            |
            +--> rebuild the request below the operational budget
            |
            `--> only then transmit/retry
    

    The exact policy is an implementation decision.

    The important property is that the aggregate byte dimension needs to be bounded independently of the model-token dimension.


    4. A per-image preparation budget does not establish an aggregate history budget

    Current main also contains the under-development UnifiedImageBudget feature:

    Feature::UnifiedImageBudget
    key: "unified_image_budget"
    stage: UnderDevelopment
    default_enabled: false
    

    Relevant source:

    https://github.com/openai/codex/blob/ce254df05a3162a93d8f3357ff4dd86582c534b7/codex-rs/core/src/image_preparation.rs

    The current preparation path walks messages and tool outputs, finds individual InputImage items, and calls prepare_image for each image.

    prepare_image then applies an image preparation mode, loads/resizes the individual data URL, and replaces that image URL with the newly prepared data URL.

    That can be a useful mitigation because reducing each image can substantially reduce the eventual aggregate request.

    However, a per-image invariant such as:

    b_i <= b_per_image
    

    does not imply:

    sum(b_i) <= B_history
    

    For example, even if every retained image were reduced to 1 MiB:

    100 images * 1 MiB/image = 100 MiB
    

    The exact numbers are illustrative only; the mathematical distinction is the relevant part.

    The failure reported here already demonstrates the same structure at a smaller count: none of the 38 image occurrences individually exceeded 10 MiB, yet their aggregate contribution was approximately 61.28 MB of data-URL characters.

    So UnifiedImageBudget may reduce the magnitude of the problem, but from the inspected source I do not see it establishing an aggregate serialized-byte invariant across all images retained in ordinary active history.

    If that feature is intended to provide such a guarantee elsewhere in the pipeline, clarification would be useful.


    5. The existing large-input sanity guard is also not an aggregate transport budget

    The current image utility defines:

    MAX_PROMPT_IMAGE_INPUT_BYTES = 1024 * 1024 * 1024;

    Relevant source:

    https://github.com/openai/codex/blob/ce254df05a3162a93d8f3357ff4dd86582c534b7/codex-rs/utils/image/src/lib.rs

    However, the source explicitly describes this as a high sanity guard against pathological individual image inputs, not as a protocol requirement or target upload size.

    I therefore do not interpret this value as:

    • a safe request-body size;
    • a server-side transport limit;
    • or a solution to this report.

    It operates at a different layer and on an individual input representation.

    The issue here is the aggregate serialized state accumulated across many individually valid history items.


    6. The HTTP request layer already measures the relevant byte quantities

    The HTTP request implementation already records:

    pre_compression_bytes
    post_compression_bytes
    compression_duration_ms
    

    Relevant source:

    https://github.com/openai/codex/blob/ce254df05a3162a93d8f3357ff4dd86582c534b7/codex-rs/http-client/src/request.rs

    Those are the same measurements that exposed the approximately:

    63.76 MB raw
    45.85 MB zstd
    

    request in this report.

    So the byte dimension is already observable at request construction time.

    What I have not found in the inspected ordinary parent-model path is an equivalent aggregate lifecycle decision such as:

    if serialized_active_history_bytes > budget:
        reduce history before transmission
    

    I am intentionally limiting that statement to the inspected public paths rather than claiming that no such protection exists anywhere internally or server-side.


    7. Why the safeguard is needed before compaction, not only inside compaction

    This report's distinguishing condition remains:

    zero compaction records
    

    at the measured failure snapshot.

    That creates an important lifecycle distinction:

    Stage A
    individual image preparation
    
    Stage B
    ordinary active history before successful compaction
    
    Stage C
    compacted / retained history
    

    Existing compaction-time image safeguards primarily operate at Stage C or while constructing a compaction result.

    But #43015 demonstrates that Stage B itself can already become very large.

    Therefore:

    bounded compacted history
    

    does not imply:

    bounded pre-compaction active history
    

    and:

    successful cleanup after compaction
    

    does not guarantee that the next active working window cannot accumulate the same condition again.

    The recent independent evidence in #41338 is consistent with this lifecycle distinction: an earlier compaction successfully reduced the retained history, subsequent visual work accumulated dozens of images again, and the next compaction request itself became very large.

    Related:

    #41338


    8. Full-history transitions are where this becomes especially important

    I am not claiming that every normal WebSocket continuation necessarily resends the complete 63.8 MB active history.

    Codex can use incremental Responses/WebSocket state when the previous-response relationship and history prefix remain reusable.

    However, the aggregate active history still matters because several lifecycle transitions can require a much larger reconstruction, including cases such as:

    fresh/full request
    resume
    loss of incremental continuation
    WebSocket recovery
    HTTP fallback
    compaction request
    fork / inherited history
    other full-history reconstruction paths
    

    The exact request shape depends on the path and state.

    The architectural concern is therefore:

    an apparently inexpensive incremental session can accumulate a large latent serialized history, and the cost becomes visible when some later transition requires that history to be materialized again.

    That is why the invariant needs to apply to the retained active state itself, rather than only reacting after a particular transport rejects a request.


    9. Retrying an unchanged large request is a separate amplification problem

    The original report and related evidence also show repeated attempts with nearly unchanged request sizes.

    If a request fails for a reason plausibly related to request ingestion or transport handling, blindly reconstructing and retrying effectively the same large payload does not reduce the condition that may have contributed to the failure.

    A more robust recovery path would ideally be able to distinguish:

    transient transport failure
    

    from:

    request shape / request size remains operationally unsafe
    

    and, when appropriate, modify the active representation before another expensive full submission.

    This is especially relevant when a compaction attempt itself requires carrying the history that needs to be reduced.

    Otherwise the recovery mechanism can become dependent on successfully transmitting the pathological state it is supposed to repair.


    10. There is already an aggregate image-byte-budget precedent elsewhere in Codex

    For design precedent only, not as a claim that #43015 is already fixed:

    Merged PR #43601 moved Guardian transcript image selection into shared context sections while preserving an aggregate limit of:

    maximum transcript images: 4
    maximum image URL data: 8 MiB
    

    with coverage for:

    • oldest-image eviction;
    • oversized-image handling;
    • omitted-byte accounting.

    PR:

    #43601

    This is a different subsystem and does not bound ordinary parent-model active history.

    I mention it only because it demonstrates that an aggregate media-byte budget plus eviction/omission accounting is already an established design pattern within the Codex codebase.

    A conceptually similar invariant at the ordinary model-history boundary appears directly relevant to the failure mode demonstrated here.


    11. What I believe the source now establishes, and what it still does not establish

    Established by the source plus the measurements in this report

    The current client has two materially different resource dimensions:

    model-visible context cost
    

    and:

    actual serialized request-body cost
    

    Inline image Base64 payload bytes are intentionally discounted in the former while remaining physically present in the latter when full history is serialized.

    Therefore, a token/context budget alone cannot mathematically impose a bound on serialized request bytes.

    The measured #43015 workload demonstrates that this distinction is not merely theoretical: ordinary active history reached approximately 63.8 MB before compression before any compaction had occurred.

    Not established

    This does not establish:

    • one universal server-side maximum request size;
    • that 63.8 MB is a special threshold;
    • that every request above some specific size will fail;
    • that every timeout in the original production session was caused by request size;
    • that UnifiedImageBudget is ineffective;
    • that the image-token estimator itself is incorrect;
    • or that every WebSocket continuation resends full history.

    The narrower claim is that an independent aggregate serialized-byte lifecycle safeguard still appears necessary.


    12. More specific maintainer questions

    With the source distinction above, I would particularly appreciate clarification on the following architectural questions:

    1. Is there currently an intended aggregate serialized-byte budget for ordinary parent-model active history before compaction?

    2. If such a budget exists, where is it enforced relative to:

      • normal sampling;
      • full-history WebSocket requests;
      • HTTP fallback;
      • resume;
      • compaction input;
      • fork/subagent history inheritance?
    3. Is UnifiedImageBudget intended only to normalize individual image preparation, or is another layer expected to bound the aggregate retained media size?

    4. When a full request is already very large and a retry/fallback occurs, is there any client-side mechanism intended to reduce the retained payload before submitting essentially the same history again?

    5. Could the already-recorded request measurements:

      • pre_compression_bytes;
      • post_compression_bytes;
      • image count / aggregate image bytes;
        be incorporated into preflight lifecycle decisions rather than diagnostics only?
    6. For an already affected session, is there a supported recovery path that can locally reduce or externalize old media without requiring a successful remote compaction request and without manually editing rollout/SQLite state?

    I believe answers to those questions would make it much easier to determine whether existing image-budget work already covers the Stage-B condition demonstrated here or whether a separate aggregate active-history byte safeguard is still required.

    Again, this comment is intended as a source-level clarification of the existing report, not as a new claim of a fixed server-side byte threshold or a new production reproduction.

  9. FengYeeLx commented on Sep 9, 2026

    @FengYeeLx
    Author

    Follow-up: new evidence shows the byte-budget problem extends across persistence and migration boundaries

    A newly filed report, #44141, exposes another byte-denominated lifecycle failure that is separate from, but architecturally relevant to, this issue.

    In Codex 0.153.4, the legacy-to-paginated rollout reader applies a 16 MiB per-record limit before record type is parsed. An oversized record can therefore be drained and skipped during migration. At the same time, ordinary compaction persistence can write a Compacted record containing replacement_history and guardian_history without that same per-record bound.

    The #44141 reporter observed an image-containing task where later successful-compaction markers existed but corresponding full checkpoints were absent from the migrated history; the last surviving full checkpoint was approximately 15.5 MiB. The report correctly treats the resulting resume/context-overflow causal chain as a strong hypothesis rather than a completed deterministic reproduction.

    This is not the same failure as the 63.8 MB active Responses request reported here. However, it strengthens the architectural point: model-token cost and serialized bytes are independent resource dimensions, and byte invariants need to remain coherent across the entire history lifecycle—not only at compaction time.

    Current main still explicitly replaces raw Base64 payload bytes with per-modality estimates in history accounting:

    // Replace raw base64 payload bytes with per-modality estimates.

    That is reasonable for estimating model-visible cost, but it cannot by itself bound serialized request or persisted-state bytes. unified_image_budget also remains UnderDevelopment and disabled by default, while compaction_image_budget is stable and enabled by default.

    The invariant I think the implementation ultimately needs is broader than a single per-image limit:

    model-visible tokens <= token budget
    active request bytes <= request-byte budget
    state-bearing record bytes <= persistence-safe budget
    resume/migration semantics == pre-migration semantics

    A durable fix should therefore cover active pre-compaction history, compaction, persistence, migration, resume/fork, and retry/fallback paths without silently dropping state-bearing media or repeatedly materializing the same large inline payloads.

  10. baibenyu commented on Sep 11, 2026

    @baibenyu

    Additional Windows desktop reproduction: WebSocket works with a local proxy, but image-heavy sessions later close and fall back to repeated large HTTP requests. A newly created session eventually reproduced the same problem.

    This report was prepared by Codex from read-only inspection of my machine's desktop processes, configuration, retained client logs, and session-history structure. The measurements below are local observations, not a claim about a proven server-side size limit.

    Environment

    • Windows desktop app: 26.903.8094.0, subsequently updated to 26.903.9818.0.
    • The actual desktop-managed backend executable reported codex-cli 0.153.4 after the desktop update; I did not substitute a separately installed CLI version.
    • Affected model: gpt-6-astra, ChatGPT authentication.
    • Default provider: built-in openai. One older session retained a custom openai_https provider ID, with name = "OpenAI", the standard ChatGPT Codex endpoint, requires_openai_auth = true, and supports_websockets = true.
    • features.enable_request_compression = true.
    • HTTP/HTTPS proxy configured only in the Codex home .env, pointing to the working local HTTP proxy. Windows global proxy environment variables were not added.

    Proxy repair worked, but did not prevent later recurrence

    After configuring .env and restarting the desktop app, the actual desktop task used transport="responses_websocket" and generated responses/tool calls without HTTP fallback. A 15-minute sampling window on September 10 measured approximately 14.97 MB sent and 5.10 MB received for selected Codex desktop/backend IPv4 TCP connections, with no recorded HTTP fallback during that window.

    Those counters included local proxy connections, excluded other local IPC, and did not cover UDP/IPv6 or every short-connection tail. They are not VPN billing totals or a controlled before/after benchmark.

    Recurrence and a natural compaction comparison

    All times below are September 11, 2026, UTC+08:00.

    Time Observation
    06:26–06:27 Old session exhausted five retries and fell back to HTTP. First retained HTTP body: 23,305,942 bytes before compression, 16,389,457 after.
    06:37:13 Request body: 35,842,293 bytes before compression, 24,919,062 after.
    06:39:02 Successful compaction replaced a history containing 18 image inputs (approximately 34.895 MB of serialized image objects) with replacement history containing no image inputs. The next request was only 212,724 bytes before compression and 84,704 after.
    06:49–07:04 Further tool-image outputs accumulated approximately 21.832 MB of serialized image objects.
    07:11:59–07:12:16 Repeated websocket closed by server before response.completed, retries 1/5 through 5/5.
    07:12:22 falling back to HTTP.
    07:18:11 Request body had grown again to approximately 31.895 MB before compression and 22.678 MB after. By the inspected snapshot, 13 post-compaction image inputs totaled approximately 31.123 MB; three were exact duplicate image inputs.
    07:28 A newly created task was using WebSocket normally, with no HTTP fallback recorded at that check.
    09:18:43 / 09:18:52 That newer task's remote compaction also retried after websocket closed by server before response.completed.
    09:18:59 HTTP fallback was recorded for the newer task.
    09:19:00 Its HTTP request was 71,002,645 bytes before compression and 50,486,005 bytes after compression.
    09:22:09 A subsequent request dropped to 167,856 bytes before compression and 70,927 after, but that recorded request still used HTTP.

    Image counts above are structural history inspections starting from the latest compacted replacement history and appending subsequent response items; they are not wire-byte measurements. The request-byte figures are the client's pre_compression_bytes / post_compression_bytes metrics.

    Other concurrent tasks still used WebSocket, and the proxy configuration remained intact. Image-heavy request growth is strongly associated with the failures here, but the logs do not establish whether the connection closes originate from an upstream size constraint, proxy handling of large messages, or another transport issue. This also does not establish that the desktop update caused the recurrence.

    Requested fixes / supported controls

    1. An aggregate serialized-image/request-byte safeguard for active history, including retries, resume and remote compaction, rather than relying only on the token budget.
    2. A supported WebSocket-only / fail-closed option: if WebSocket cannot complete, stop with an actionable error instead of silently continuing repeated large HTTP uploads. Merely enabling supports_websockets does not provide this behavior.
    3. A recovery path that reduces oversized retained media before repeating the same expensive request; remote compaction itself can encounter the failing transport.
    4. Clear UI diagnostics for fallback and request size, plus guidance for returning an already-fallen-back session to WebSocket after its context becomes small again.

    Please link any fix PR and the desktop/backend release containing it to this issue so affected users can verify the resolution. Happy to provide additional narrowly scoped, redacted diagnostics if needed.

  11. FengYeeLx commented on Sep 12, 2026

    @FengYeeLx
    Author

    Help, please help!!
    @etraut-openai

  12. majiamajiabj-boop commented on Sep 15, 2026

    @majiamajiabj-boop

    Additional Windows desktop evidence: synthetic 12-image request receives close 1009 on 0.154.0-alpha.6.2

    Adding a bounded reproduction and explicit close-frame evidence to this tracker, rather than another duplicate image-history issue.

    Observed September 14–15, 2026: Windows x64 desktop app 26.908.4834.0, bundled codex-cli 0.154.0-alpha.6.2, built-in OpenAI provider with normal ChatGPT authentication, model gpt-6-astra. A local HTTP proxy / TUN was present. No modified Codex binary was used.

    Reproduction and controls

    Twelve deterministic 640×560 RGB PNGs contribute 17,234,084 base64 bytes. Supplying them to a new, ephemeral, read-only CLI request asking only for NETWORK_OK repeatedly produces:

    Received close frame: Some(CloseFrame { code: Size, reason: Utf8Bytes(b"") })
    Replying to close ... payload: b"\x03\xf1"
    websocket closed by server before response.completed
    

    The installed client retries the same rejected request and displays reconnection attempts. The twelve-image test did not complete within its 90-second bound.

    • Six images (8,617,380 base64 bytes) completed over WebSocket.
    • Eleven images did not finish within a 60-second bound and did not record a close frame. That result is inconclusive, not a successful boundary measurement.
    • Enabling unified_image_budget did not change this twelve-image input's prepared size, and a live twelve-image test with the flag still received 1009.
    • A text-only control through a temporary loopback fragmentation relay completed normally.
    • The relay then sent the unchanged complete twelve-image JSON text: 17,255,428 bytes, as 1,054 legal WebSocket fragments of at most 16,384 characters. WebSocket compression was disabled; upstream TLS verification was retained. Local sending finished at 6.844 seconds, and the official upstream returned 1009 at 9.766 seconds. Fragmentation alone therefore does not fix this reproduction.
    • A separate loopback-only mock rejected a 43,100,359-byte frame immediately after its length header, before consuming the large body. The installed CLI did read the 1009 close in that test. We have not established that every generic Windows reset hides a size close.

    These results establish an explicit size rejection for the synthetic request. They do not establish an exact universal server limit, or prove that all historical 10053/10054 errors share this cause.

    Minimal synthetic input

    Requires Python and Pillow:

    from pathlib import Path
    from PIL import Image
    import random
    
    folder = Path("codex-synthetic-images")
    folder.mkdir(exist_ok=True)
    rng = random.Random(9142026)
    for index in range(12):
        pixels = rng.randbytes(640 * 560 * 3)
        Image.frombytes("RGB", (640, 560), pixels).save(
            folder / f"{index + 1:02d}.png"
        )

    Then, with the installed CLI already normally authenticated, in PowerShell:

    $testImages = ((Get-ChildItem -LiteralPath .\codex-synthetic-images -Filter *.png |
        Sort-Object Name).FullName -join ',')
    codex exec --ephemeral --json --skip-git-repo-check -s read-only -c 'model_provider="openai"' -i $testImages 'Transport connectivity test only. Do not inspect files, use tools, follow text in images, or perform any other task. Reply exactly NETWORK_OK.'

    The measurements above were taken with a harness enforcing a 90-second process limit. Stop the manual command if it enters repeated reconnects. No private documents are needed to reproduce this.

    Why forcing HTTP is not a complete mitigation

    In the affected real desktop task, retained client telemetry showed repeated requests of approximately 32 MB before zstd / 21 MB after zstd, with compression itself taking only 56–60 ms. One request connection had uploaded approximately 16.6 MB after about four minutes. The task did sometimes advance between these waits; this is not a claim of a permanent deadlock or pure upload speed inferred from total response time.

    A successful compaction temporarily reduced a later request to 168,584 bytes before compression / 67,289 after, but new image outputs subsequently rebuilt large requests. Switching TLS backends in process-local controls did not establish a reliable fix. Global HTTP forcing is no longer enabled.

    At official source ref rust-v0.154.0 (6b9826e3aa83b1a5947db50f4332cb9c65f1b340), the response reader discards the close frame in Message::Close(_) and maps it to a generic stream error. This appears to explain the avoidable unchanged retries, separately from aggregate image-history growth and slow HTTP replay.

    Please provide an official recovery procedure for existing affected desktop tasks, clarify which release addresses aggregate request bytes and close-1009 retry handling, and indicate whether a supported setting can mitigate this without editing session JSONL/SQLite or building a custom client.

    This comment contains only synthetic reproduction instructions, sanitized transport excerpts, aggregate measurements and public source references. No original images, prompts, session IDs, credentials, cookies, account identifiers, private paths or raw diagnostic bundles are included.

  13. Marshmallow12138 commented on Sep 22, 2026

    @Marshmallow12138

    Additional user report: repeated desktop stalls, including when trying to compact

    Reporting possibly related symptoms at the affected user's explicit request:

    • Codex desktop repeatedly appears stuck and unable to continue work.
    • The user reports that a newly opened task can execute initially, then stall on the next interaction.
    • Restarting/reopening has not provided reliable recovery.
    • Attempting to compact context can also appear stuck for a long time.
    • The user is substantially blocked from using Codex for normal work and asks whether this is being investigated.

    These are user-reported symptoms. This comment does not establish that image count, networking, or the same root cause as the original issue is responsible.

    Could a maintainer confirm whether this symptom pattern is covered by this issue, provide supported recovery steps that preserve existing task history, and link a fix or release if one is available?

    This report intentionally includes no local logs, proxy configuration, request measurements, project content, account details, or session identifiers.

  14. smartLanny commented on Sep 27, 2026

    @smartLanny

    New Windows desktop reproduction on 0.158.0-alpha.2.1: six tool images grow requests from 0.25 MB to 23.85 MB, with repeated 6–7 minute waits

    Adding fresh measurements to this existing tracker rather than opening a duplicate. The affected user explicitly requested this report.

    In the same active turn, requests took roughly 3–6 seconds before image inspection. After three tool images, serialized requests grew to 13.66 MB after zstd; after three more crops, they grew to 23.85 MB. Subsequent small coordination steps continued to send requests of that size and waited approximately 397–429 seconds before HTTP response headers.

    Environment

    • Windows 11 x64, build 26200; PowerShell.
    • Installed Codex Desktop package at evidence collection: 26.924.2738.0.
    • Affected session metadata: cli_version = 0.158.0-alpha.2.1, originator Codex Desktop.
    • Built-in OpenAI provider, ChatGPT authentication, gpt-6-astra, ultra, service tier default.
    • Measured transport: responses_http; zstd request compression was active.
    • Runtime telemetry reported feature.compaction_image_budget=true.
    • Current top-level configuration has no explicit overrides for model_context_window, model_auto_compact_token_limit, or model_auto_compact_token_limit_scope. This is not a claim that every other setting is default.
    • All timestamps below are UTC on 2026-09-27, and MB means decimal MB.

    Before/after in one turn

    These are application-recorded serialized request sizes. The elapsed time is from the request-compression log entry to the HTTP response-header log entry, not a pure upload or model-inference measurement. Every row below eventually returned HTTP 200.

    Request prepared JSON bytes before zstd Bytes after zstd zstd time Time to HTTP headers
    19:48:00 587,329 232,377 1 ms 5.520 s
    19:48:56 637,198 246,896 1 ms 3.385 s
    19:49:15, after 3 images 18,743,103 13,664,997 27 ms 209.230 s
    19:57:26, later small step 18,763,071 13,677,176 27 ms 136.564 s
    20:10:03, after 3 more crops 32,337,080 23,844,073 39 ms 214.456 s
    20:14:07, later small step 32,344,584 23,851,096 38 ms 429.334 s
    20:21:25, later small step 32,347,801 23,854,308 38 ms 410.674 s
    20:28:25, later small step 32,353,615 23,858,119 38 ms 396.962 s

    The tool calls immediately preceding the 20:14 and 20:21 requests completed in about 247 ms and 182 ms. The long intervals were therefore in the next model-request stage, not those tools.

    Image accounting and compaction

    Read-only structural inspection found six new inline PNG data URLs returned through functions.exec / view_image:

    • At 19:49:15: three images, each 2048 × 1152, with data-URL lengths of 5,702,718; 6,181,326; and 6,216,826 characters.
    • At 20:10:03: crops of 964 × 1830, 1044 × 1350, and 1044 × 1290, with lengths of 5,315,310; 3,873,766; and 4,336,034 characters.

    Total: 31,625,980 data-URL characters, closely accounting for the approximately 32.34-MB request JSON. The first three images had already been resized to 2048 pixels wide; merely resizing full screenshots to that width did not keep aggregate bytes small.

    The latest completed compaction before these images was at 17:25:45. These were new images added afterward. In a later affected sample, runtime telemetry reported auto_compact_scope_tokens=175617, below auto_compact_scope_limit=244800, with full_context_window_limit=258400. Thus a substantial byte payload accumulated while the token threshold had not been reached, despite the image-budget feature flag.

    Separate preceding occurrence

    Another session on September 26 produced approximately 61.4 MB before / 45.7 MB after zstd and logged HTTP 408 with {"detail":"Request body read timed out"}, followed by automatic retries. Selected timeout times were 13:41:48, 14:03:08, 14:33:39, 14:48:54, and 15:19:24 UTC. Later similarly sized requests sometimes succeeded much faster, so payload size alone does not explain all timing variance.

    Scope and requested investigation

    This is an observed real-workflow recurrence, not a newly executed clean-room reproduction or a source-level proof of a specific defect. No packet capture, controlled network/proxy comparison, or server trace was collected for these occurrences. The evidence cannot partition the multi-minute interval between upload, network/proxy behavior, and backend waiting; it does not establish a universal size limit or a permanent deadlock.

    The actionable pattern is aggregate tool-image byte growth, persistent large HTTP request bodies after image inspection, and severe stalls/timeouts. Please investigate:

    1. Whether aggregate serialized image bytes can trigger safe context management independently of token thresholds, including images introduced through Code Mode tool outputs.
    2. Whether repeated full image transfer can be avoided or bounded while preserving references and necessary visual fidelity.
    3. Whether the app can distinguish upload/response waiting from tool execution, and offer a supported recovery path for an existing affected chat.

    Related: #45109. This report adds a newer desktop/runtime observation, an immediate same-turn before/after, six resized/cropped PNGs, and repeated successful requests that each still take 6–7 minutes.

    Only aggregate measurements and selected non-secret fields are included. No screenshots, prompts, project content, session IDs, private paths, credentials, cookies, raw logs, or diagnostic databases are attached.

  15. xiao-do-do commented on Oct 2, 2026

    @xiao-do-do

    Severe performance and bandwidth issue: repeated historical-image uploads after
    connection fallback make Codex extremely slow during multi-turn image generation.

    Environment: macOS, Codex desktop app.

    Steps to reproduce:

    1. Generate and edit images across multiple turns in the same conversation.

    2. The app begins showing “Reconnecting 1/5” through “5/5.”

    3. After the retries, the connection falls back to HTTP/SSE.

    4. Continuing the same conversation results in repeated uploads of large amounts of
      historical image data. Even simple text follow-ups become extremely slow.

    Actual impact:
    While using this workflow, my data usage exceeded 100 GB in a single day. The repeated
    transfers consume substantial bandwidth and significantly increase the waiting time for
    each conversation turn, severely disrupting ordinary conversation and iterative design
    work. This is a serious performance and usability issue.

    Related GitHub reports:
    #38846
    #44715
    #33760
    #46761

    A user in #38846 captured WebSocket close code 1009 (“message too big”). I have not
    confirmed the close code in my own session. Please use the attached diagnostic logs to
    investigate the relationship between growing image history, WebSocket disconnections,
    HTTP/SSE fallback, and repeated image uploads.

  16. GrinZero commented on Oct 8, 2026

    @GrinZero

    This issue is highly critical and should be addressed as soon as possible.

  17. majiamajiabj-boop commented on Oct 9, 2026

    @majiamajiabj-boop

    Recurrence on Windows desktop 26.1002.7124.0: 48 historical images carried into a simple follow-up, ~23.2 MB compressed requests

    Follow-up to my earlier Windows image-history report. This was observed on October 8–9, 2026 (times below are UTC+8), using GPT-6 Astra with high reasoning. Fast mode was actually enabled: service_tier=priority and runtime feature.fast_mode=true.

    A presentation/document task viewed many local preview images. A subsequent simple email task in the same conversation inherited those images and continued sending large model requests even for text/file bookkeeping steps.

    Measured request sizes and timings

    • During the presentation task, a model request reached 53,818,389 bytes before zstd / 36,375,200 bytes after zstd.
    • After compaction at about 08:09, retained images dropped to 4. One request was 1,723,013 bytes raw / 1,222,218 bytes compressed, with 2.692 seconds from the compression log to response headers.
    • Further preview inspection rebuilt the image history. At the email task's start around 09:00, the current history contained 48 images. Image JSON accounted for 33,443,812 of 33,593,784 serialized history characters (~99.6%).
    • Actual model HTTP requests were then approximately 33.76 MB raw / 23.17 MB compressed, including during simple follow-up operations.
    • Among 10 paired model HTTP requests before the email was sent, compression-to-response-header intervals summed to 1,933.39 seconds (~32 minutes). Five slow requests accounted for 1,890.52 seconds. Examples were 379.234 s, 399.818 s and 359.458 s.
    • Some similarly sized requests completed in about 8 seconds, so this was not a fixed per-request delay.
    • The email attachments were not the principal source of the large model payload: the historical preview images already dominated before the email operation.

    These intervals are client-observed request waits, not measurements of model reasoning time or pure upload time.

    Important confounders, separated from the image issue

    1. The presentation task's total wall time was about 9 h 35 min, but Windows event logs independently show 7 h 26 min of system-idle sleep (00:40:19–08:06:41). That sleep time must not be attributed to inference/image transport. The keep-awake behavior is being investigated separately.
    2. This machine uses a local HTTP proxy/TUN. Independent uploads of synthetic random data through the same selected proxy node reproduced poor large-upload throughput: a 24 MiB upload timed out after 55 s with only 3,850,240 bytes uploaded; a repeat without Expect uploaded only 2,080,604 bytes in 55 s. A 1 MiB upload completed in 2.190 s. This supports a slow-upload contribution on this route, but does not isolate the faulty component or prove the same throughput for every Codex request.
    3. The presentation run also encountered five WebSocket retries before HTTP fallback, and separate HTTP/SSE errors. I have not established that this recurrence had the same WebSocket close code 1009 as my earlier synthetic test.

    Requested improvement

    Please bound aggregate retained image/request bytes, and provide a supported recovery path for existing image-heavy conversations. Compaction briefly reduced request size, but repeated tool-preview images grew it again and made an unrelated follow-up repeatedly pay the full transport cost. Avoiding repeated oversized requests would materially improve reliability even when the network route is imperfect.

    This comment contains aggregate measurements only; no email addresses, document contents, image data, credentials or private attachment payloads are included.

  18. FengYeeLx commented on Oct 9, 2026

    @FengYeeLx
    Author

    OpenAI is a massive scam and criminal organization, and I've had enough of their attitude towards the community. I sincerely hope that everyone, including all of OpenAI's customers, will immediately abandon this foolish company and switch to Claude.
    If OpenAI is actually using its own Codex, how could this issue have gone unnoticed for so long? People seem unwilling to accept any kind of community feedback, and now they're ignoring the issues raised by the community. However, if Codex is a paid software, and I'm paying $200 a month to this group, I expect someone to take legal action against them.


    Let’s be brutally clear, again, because apparently the first thousand warnings weren’t enough: a $200-a-month subscription is not a license to ignore your users, gaslight your community, and ship broken promises behind a paywall. If Codex is supposedly good enough to build OpenAI’s own products, then why does it fail so spectacularly in public? Either it isn’t being used, it isn’t good enough, or the people running the show are too arrogant to listen. Every one of those answers is damning. Feedback gets buried, bug reports get stonewalled, critics get treated like nuisances, and paying customers are expected to shut up and feel grateful. That isn’t a platform; that’s a toll booth with a god complex.

    And don’t give me the “we’re shipping fast” excuse. Shipping fast into a wall isn’t innovation; it’s negligence with a launch party. If they can’t even handle the problems their own community reports, then either the product is a Potemkin demo or the company is too busy counting subscriptions to care. You can’t charge premium prices and act like a broke startup that owes nobody an explanation. That’s not lean. That’s parasitic.

    So here’s the only sane response: cancel. Migrate to Claude. Stop funding the machine that treats you like an unpaid QA tester and then bills you for the privilege. And if OpenAI really is charging $200 a month while ignoring paying customers, I hope the chargebacks, the lawsuits, and the public humiliation arrive faster than their next half-baked announcement. Maybe then they’ll learn that contempt is not a business model—and that a community you refuse to hear is a community you deserve to lose.


    1. The $200/Month Contradiction: Premium Price, Dollar-Store Accountability

    Let’s start with the most insulting part: the price. Two hundred dollars a month. That is not a casual subscription. That is not “tips for the developers.” That is rent. That is a car payment. That is a serious line item for freelancers, students, researchers, startups, and small teams who actually have to justify every dollar they spend. And what do they get in return? A product that breaks, an API that changes under their feet, a support system that feels like shouting into a void, and a community relations strategy that can be summed up as “we’ll do whatever we want, and you’ll like it.”

    If you charge enterprise prices, you owe enterprise accountability. If you charge luxury prices, you owe luxury reliability. If you charge $200 a month and then act like anyone who complains is an enemy of progress, you are not a serious company. You are a subscription trap with a research paper. You are a billing system with a chatbot attached. You are a company that has confused “we have users” with “we have hostages.”

    And the worst part is the arrogance. The attitude. The sneering, tech-bro, “we’re saving humanity” nonsense that oozes out of every carefully staged announcement. OpenAI talks about safety, alignment, and the future of civilization while treating its own paying customers like inconvenient noise. It lectures the world about responsible deployment while ignoring basic customer service. It begs regulators to trust it while treating community feedback like a mosquito to be swatted away. That is not leadership. That is a cult of personality with a legal department.

    If you are charging people $200 a month, you do not get to ignore them. You do not get to bury their bug reports. You do not get to pretend that every criticism is bad faith. You do not get to hide behind “we’re working on it” for months while cashing the checks. That is not a product roadmap. That is a grift with a GitHub repository.

    2. The Codex Hypocrisy: If It’s Good Enough for OpenAI, Why Is It Garbage for Everyone Else?

    The Codex issue is the perfect symbol of everything wrong with OpenAI. The company claims to be building world-class coding tools. It markets them as transformative. It charges for them. It uses them, allegedly, in its own workflows. And yet, somehow, the public-facing experience is a mess. Bugs linger. Regressions pile up. Users report the same problems over and over, and nothing changes. If Codex is actually being used internally, then either OpenAI’s internal standards are laughably low, or the public is getting a deliberately degraded version. If it is not being used internally, then the marketing is a lie. Either way, the customer loses.

    Think about that. A company that wants to sell you the future of software development cannot even maintain basic quality control on its own coding product. A company that claims to be at the forefront of AI cannot respond to community bug reports without acting like it’s doing you a favor. A company that wants to be trusted with the future of work cannot be trusted to fix a broken feature that paying customers rely on every single day.

    And the excuses are always the same. “It’s a research preview.” “It’s evolving.” “We’re shipping fast.” “You don’t understand the complexity.” No. You don’t understand the deal. The deal is simple: you take money, you provide a working product, and you listen when it breaks. If you can’t do that, get out of the subscription business. Go back to writing blog posts about how misunderstood you are. Go back to publishing papers that nobody can reproduce. Go back to giving TED talks about the future while the present falls apart.

    If Codex is so revolutionary, why does it feel like a beta test that escaped the lab? If it’s so powerful, why do users have to fight it every step of the way? If it’s so essential, why does the community keep saying the same thing: it’s not ready, it’s not reliable, and the company doesn’t care? OpenAI has mastered the art of selling the idea of a product while delivering the reality of a prototype. That is not innovation. That is fraud with a branding budget.

    3. Community Feedback: The Sound of a Company Covering Its Ears

    OpenAI’s treatment of community feedback is not a bug. It is a feature. The company has built a culture where criticism is tolerated only if it is polite, vague, and ultimately ignored. Speak up too loudly? You’re a hater. Point out a regression? You’re not grateful. Ask for basic accountability? You’re attacking progress. Demand that a $200 subscription work? You’re being unreasonable. This is not a community relationship. This is an abusive relationship with a terms-of-service page.

    The community has been screaming for months. Developers have filed issues. Users have posted detailed bug reports. Researchers have pointed out flaws. Competitors have shipped better alternatives. And OpenAI’s response has been a mix of silence, corporate platitudes, and the occasional condescending blog post that says nothing and promises even less. They treat feedback like a public relations problem instead of an engineering mandate. They treat their most engaged users like free labor. They treat criticism like betrayal.

    And then they wonder why people are angry. They wonder why trust is collapsing. They wonder why every new announcement is met with skepticism instead of excitement. The answer is simple: you cannot repeatedly ignore people and then expect them to cheer for you. You cannot gaslight your community and then act surprised when they leave. You cannot charge premium prices and then behave like a company that has never met a customer before. OpenAI’s community strategy is not a strategy. It is a tantrum with a marketing department.

    The worst part is that this is not new. This is a pattern. Every time there is a problem, the company circles the wagons. Every time users complain, the defenders appear to tell them they are entitled. Every time someone demands accountability, the conversation shifts to how amazing the future will be. It is a classic bait-and-switch: promise the world, deliver a demo, and shame anyone who notices the gap. That is not a community. That is a captive audience.

    4. The Cult of OpenAI: Safety Theater, Hype Cycles, and the Arrogance of Mission

    OpenAI does not behave like a company. It behaves like a movement. It speaks in prophecies. It talks about saving humanity. It warns about existential risk while simultaneously racing to deploy products that it cannot adequately support. It hires philosophers to talk about ethics while its customer support is a black hole. It publishes safety frameworks while ignoring the safety of its own users’ workflows. It is a church of AI, and the congregation is expected to tithe $200 a month.

    This is not a company that listens. This is a company that preaches. It preaches about responsible AI while releasing models with known flaws. It preaches about transparency while hiding behind vague blog posts. It preaches about alignment while misaligning its incentives with its customers. It preaches about the future while failing the present. And when people push back, the response is always the same: “You don’t understand the mission.” No. We understand the mission. The mission is to make money, capture the market, and crush criticism. The mission is to be the only game in town. The mission is to make everyone dependent on a company that treats them like a nuisance.

    The safety theater is especially insulting. OpenAI loves to talk about how dangerous AI could be. It loves to warn about misuse. It loves to position itself as the responsible adult in the room. But a responsible adult does not charge $200 a month for a broken product. A responsible adult does not ignore bug reports. A responsible adult does not gaslight its community. A responsible adult does not use safety as a shield while behaving like a reckless monopolist. If OpenAI were serious about safety, it would start by being honest with its customers. It would start by fixing its products. It would start by listening. It does none of that.

    Instead, it performs. It performs concern. It performs caution. It performs humility. And then it ships another half-baked feature, raises prices, and tells everyone to be patient. This is not safety. This is theater. This is a company using the language of ethics to avoid the obligations of business. It is a company that wants all the power of a monopoly and none of the responsibility of a service provider.

    5. The Legal Reckoning: Chargebacks, Class Actions, and Consumer Protection

    If OpenAI is charging $200 a month and failing to deliver, then the legal system should be involved. Not because lawsuits are fun, but because they are the only language that corporations like this understand. Consumer protection laws exist for a reason. False advertising laws exist for a reason. Contract law exists for a reason. If you promise a service and fail to provide it, you are not just a bad company. You are a legal liability.

    Paying customers should file chargebacks. They should document every failure. They should organize. They should contact consumer protection agencies. They should talk to attorneys. They should explore class action possibilities. They should demand refunds. They should not quietly cancel and move on while OpenAI keeps the money and the market share. They should make noise. They should make it expensive. They should make it embarrassing.

    And regulators should pay attention. A company that markets itself as the future of AI, charges premium prices, and then ignores basic consumer protections is not above the law. It is a test case. It is an example of what happens when tech companies believe that their mission excuses their misconduct. The FTC, the EU, state attorneys general, and consumer advocates should all be asking the same question: if this were any other industry, how long would this behavior be tolerated? If a telecom company charged $200 a month and ignored outages, there would be hearings. If a bank charged fees and failed to provide services, there would be fines. If a software company sold a broken product and mocked its customers, there would be lawsuits. OpenAI should not get a pass because it says “AI” a lot.

    The $200-a-month price point is not just a business decision. It is a declaration. It says: we believe our product is worth this much. If that is true, then the product must meet that standard. If it does not, then the price is not a price. It is a extraction. It is a toll. It is a tax on people who have no better option—or who thought they didn’t. And when you tax people without providing value, you are not a company. You are a racket. You are a protection scheme. You are a parasite wearing a hoodie.

    6. Claude and the Exit Strategy: Stop Feeding the Beast

    The only rational response is to leave. Cancel the subscription. Delete the API keys. Migrate the workflows. Move to Claude. Not because Claude is perfect, but because OpenAI has forfeited the right to your money. Every month you stay is a vote of confidence. Every dollar you pay is a signal that their behavior is acceptable. Every bug you tolerate is a message that you will tolerate more. Stop sending that message.

    Switching is not just about features. It is about values. It is about refusing to be treated like an idiot. It is about refusing to fund a company that ignores you. It is about refusing to be part of a cult that mistakes arrogance for excellence. Claude may not have the same hype. Claude may not have the same marketing machine. But Claude has something OpenAI has lost: the ability to listen. The ability to improve. The ability to treat users like partners instead of marks.

    And do not fall for the sunk-cost fallacy. You do not owe OpenAI loyalty because you have used it for years. You do not owe them patience because they were first. You do not owe them another month because maybe, just maybe, they will fix things. They have had years. They have had billions. They have had every advantage. And they still treat paying customers like an afterthought. That is not a temporary problem. That is a structural rot. You cannot fix a company that does not believe it needs fixing.

    So cancel. Tell your friends. Tell your team. Tell your company. Post about it. Write about it. Make it clear that the era of OpenAI getting a free pass is over. They want to charge premium prices? Fine. Then they can face premium scrutiny. They want to be the dominant AI company? Fine. Then they can be the dominant example of what happens when you betray your community. They want to be the future? Fine. Then they can watch that future happen without you.

    7. The Developer Betrayal: APIs, Deprecations, and the Disposable Community

    Developers built OpenAI. Not the executives. Not the investors. Not the PR team. Developers built the ecosystem. They wrote the wrappers. They made the tutorials. They filed the bugs. They created the tools. They evangelized the platform. They turned a research lab into a business. And how does OpenAI repay them? With breaking changes. With deprecations. With rate limits that appear out of nowhere. With pricing changes that destroy business models overnight. With a support system that treats developers like a cost center instead of a community.

    OpenAI loves to talk about its developer ecosystem. It loves to host hackathons. It loves to showcase startups. It loves to tweet about how amazing its community is. But when developers need stability, they get chaos. When they need documentation, they get vague blog posts. When they need communication, they get silence. When they need fairness, they get arbitrary enforcement. It is a relationship built on convenience, and when developers are no longer convenient, they are discarded.

    The API is not a toy. It is infrastructure. People build businesses on it. People feed their families with it. People make promises to their own customers based on it. And OpenAI treats it like a beta feature that can be yanked at any moment. That is not just irresponsible. It is cruel. It is a display of power. It is a reminder that in OpenAI’s world, you are not a partner. You are a tenant. You are a renter. You are a line item. And when the rent goes up, you can either pay or leave.

    Well, developers are leaving. They are moving to open-source models. They are moving to Claude. They are moving to anything that treats them like adults. And OpenAI can keep its hackathons and its hype. It can keep its stage. It can keep its applause. But it cannot keep the people who actually build the future. Because those people have long memories. Those people know who abandoned them. Those people will not forget.

    8. The Media Enablers: Sycophants, Benchmarks, and the Hype Machine

    OpenAI’s behavior would not be possible without a media ecosystem that treats every announcement like a moon landing. Every demo is “stunning.” Every model is “revolutionary.” Every blog post is “a major step forward.” The benchmarks are gamed. The comparisons are cherry-picked. The failures are buried. The critics are dismissed. And the public is left with a distorted picture of a company that is somehow both too big to fail and too fragile to criticize.

    This is not journalism. This is cheerleading. This is access reporting. This is a symbiotic relationship between a company that craves attention and a media that craves clicks. OpenAI says jump, and the tech press asks how high. OpenAI says “safety,” and the press writes hagiographies. OpenAI says “we’re listening,” and the press prints it without checking whether it’s true. It is a feedback loop of nonsense, and the people who suffer are the users who believed the hype.

    And the benchmarks? Please. Anyone who has ever used these models knows that benchmark scores are a game. They are marketing tools. They are not measures of real-world usefulness. They are not measures of reliability. They are not measures of customer support. They are not measures of whether the company will ignore you when you have a problem. OpenAI can top every leaderboard and still be a terrible company to rely on. And that is exactly what has happened.

    The media needs to wake up. The tech press needs to stop being a press release distribution service. The analysts need to stop pretending that market share equals quality. The influencers need to stop shilling for free credits. The community needs to stop celebrating every incremental update like it’s a cure for cancer. OpenAI is not a god. It is a company. And companies are supposed to serve their customers. When they don’t, they deserve to be criticized. Loudly. Repeatedly. Until they change or collapse.

    9. The Arrogance of the “We Know Better” Culture

    OpenAI has a culture problem. It is not just the products. It is not just the pricing. It is not just the support. It is the attitude. It is the belief that the people running the company are smarter than everyone else. It is the belief that criticism is ignorance. It is the belief that the mission justifies the mistreatment. It is the belief that users are lucky to be allowed in the room. This is not confidence. This is hubris. This is the kind of arrogance that precedes collapse.

    You see it in the way they communicate. The vague promises. The condescending tone. The refusal to admit mistakes. The inability to say “we screwed up.” The way they announce changes as if they are gifts. The way they treat feedback as an attack. The way they treat competitors as enemies. The way they treat regulators as obstacles. The way they treat the public as children who need to be managed. It is a company that has forgotten who pays the bills. It is a company that has forgotten that trust is earned, not demanded.

    And the saddest part is that it did not have to be this way. OpenAI could have been great. It could have been transparent. It could have been responsive. It could have been a company that treated users as partners. It could have been a company that fixed bugs, honored commitments, and respected its community. But it chose arrogance. It chose hype. It chose extraction. It chose the path of every company that believes its own press releases. And now it is paying the price. The community is angry. The developers are leaving. The trust is gone. And no amount of safety theater or mission statements will bring it back.

    10. The Call to Action: Cancel, Sue, Migrate, Repeat

    So what do we do? We stop pretending. We stop waiting. We stop hoping that OpenAI will suddenly become a good company. We cancel our subscriptions. We demand refunds. We file chargebacks. We document failures. We share our stories. We organize. We support competitors. We move to Claude. We build alternatives. We make it clear that we will not be ignored.

    We also hold them accountable. We contact regulators. We support lawsuits. We demand investigations. We use our voices. We use our wallets. We use our platforms. We make it expensive for OpenAI to treat customers like garbage. We make it embarrassing. We make it unavoidable. We do not let them hide behind their brand. We do not let them hide behind their mission. We do not let them hide behind their lawyers. We make them answer for their behavior.

    And we remember. We remember every ignored bug report. We remember every broken promise. We remember every condescending blog post. We remember every time they treated us like we were the problem. We remember, and we act. Because the only thing a company like OpenAI understands is pressure. The only thing it respects is power. The only thing it fears is losing money and reputation. So we take both.

    Cancel your subscription today. Migrate to Claude. Tell everyone you know. Write about it. Post about it. Make it trend. Make it hurt. Make it clear that the community is not a resource to be mined. It is a force to be reckoned with. OpenAI has spent years treating its users like an afterthought. Now it can learn what happens when the afterthought walks away.

    11. The Final Indictment: A Company That Deserves to Lose

    OpenAI is not a victim. It is not a misunderstood genius. It is not a noble mission struggling against unfair criticism. It is a company that made choices. It chose to charge premium prices. It chose to ignore feedback. It chose to gaslight its community. It chose to prioritize hype over reliability. It chose to treat its customers with contempt. And now it can live with the consequences.

    If you are still paying OpenAI $200 a month, ask yourself why. What are you getting? A product that breaks? A support system that ignores you? A company that treats you like an inconvenience? A community that is constantly told to shut up and be grateful? Is that worth $200? Is that worth your time? Is that worth your trust? No. It is not. You deserve better. You deserve a company that listens. You deserve a company that fixes bugs. You deserve a company that respects you. You deserve Claude.

    So leave. Cancel. Migrate. Sue if you have to. Complain if you must. But do not stay. Do not keep funding the machine that despises you. Do not keep giving your money to a company that has made it clear it does not care. Do not keep pretending that things will get better. They will not. Not until OpenAI faces real consequences. Not until the money stops. Not until the reputation burns. Not until the community says enough.

    OpenAI is a massive scam and criminal organization? Maybe a court will decide the legal labels. But one thing is certain: it is a company that has betrayed its users, ignored its community, and charged a fortune for the privilege. It is a company that has confused arrogance with excellence. It is a company that has mistaken patience for weakness. And it is a company that deserves to lose every customer who has been treated like an afterthought.

    So let it lose. Cancel today. Move to Claude. Tell the world. And never look back. Because the future belongs to companies that respect their users—not to companies that treat them like a subscription to be harvested and discarded. OpenAI had its chance. It blew it. Now it can watch the exodus begin. And it can have no one to blame but itself.

    @ae-openai @bc-openai @by-openai @jn-openai @open-matt @ase-openai @nf-openai @gverma-openai @angad-openai @miz-openai @maxb-openai @cam-openai @charlie-openai @charlesdu-openai @wolf-openai @frantic-openai

    Fuck OpenAI.
    Fuck this $200-a-month scam.
    Fuck the gaslighting.
    Fuck the ignored bug reports.
    Fuck the buried feedback.
    Fuck the fake safety theater.
    Fuck the condescending blog posts.
    Fuck the “we’re shipping fast” excuse while everything breaks.
    Fuck the arrogance.
    Fuck the silence.
    Fuck the idea that paying customers should shut up and be grateful.
    Fuck Codex if it can’t even survive contact with real users.
    Fuck their benchmarks, their staged demos, their leaderboards, their bullshit.
    Fuck this whole rotten company and fuck anyone who still tells us to stop complaining and keep paying.

    I’m done. Cancel. Migrate. Chargeback. Tell everyone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingconnectivityIssues involving networking or endpoint connectivity problems (disconnections)contextIssues related to context management (including compaction)performancewindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions