Repository navigation
Codex App: text-log attachment can trigger “Request blocked” and poison subsequent turns #32177
Description
What version of the Codex App are you using (From “About Codex” dialog)?
26.707.31428
What subscription do you have?
ChatGPT Team
What platform is your computer?
Darwin 25.5.0 arm64 arm
What issue are you seeing?
In Codex App, attaching a plain-text application log to an established thread can cause the turn to fail after approximately 3–5 seconds with only:
Request blocked.
The failure is persistent within that thread. Sending a subsequent short message without any attachment also fails with the same generic error because the rejected attachment turn remains in the conversation history.
The affected turns complete without an assistant response. Local thread events show a completed task with no final assistant message. The desktop logs do not show an authentication, rate-limit, or HTTP 401/403/429 failure.
This reproduced with multiple different plain-text logs. The logs contained ordinary service diagnostics, model-loading messages, token counts, and request metadata. They did not contain credentials.
A control request in a new, short thread succeeds with the same account and model.
What steps can reproduce the bug?
- Open Codex App and use an established local-project thread with substantial completed history.
- Confirm that a normal turn still succeeds.
- Attach a plain-text service log. Reproduced attachment sizes ranged from approximately 42 KB / 425 lines to 115 KB / 1,094 lines.
- Ask Codex to inspect or summarize the log.
- Observe that the turn ends after approximately 3–5 seconds with
Request blocked.and no assistant message. - Send a short follow-up without an attachment.
- Observe that the follow-up is also blocked because the rejected attachment turn remains in the thread history.
- Create a new thread in the same project and send a short prompt without carrying over the attachment. Observe that it succeeds.
Relevant diagnostics:
- Model:
gpt-5.6-sol, medium reasoning. - Last successful turn before the attachment used 160,985 input tokens with a reported 353,400-token context window.
- Account usage was below 10%; no rate-limit-reached state was reported.
- Directly resuming the affected thread through the bundled CLI reproduces
ERROR: Request blocked., so this is not only a stale renderer banner. - Session identifiers are intentionally omitted for privacy, but can be supplied privately if maintainers provide a secure channel.
What is the expected behavior?
Codex App should do one of the following:
- Accept the attachment when the combined request fits the supported context and request limits.
- Proactively compact, truncate, or summarize the attachment/history before sending.
- Reject the attachment before creating the turn and display a specific actionable error, such as an attachment-size or request-size limit.
A failed attachment turn must not poison the thread. A subsequent message without the attachment should work, or the UI should provide a clear way to remove/rollback the rejected turn.
Additional information
- Reproduced after a full app restart.
- Clearing GUI caches and refreshing authentication did not change the behavior.
- Authentication and ordinary requests remained functional.
- No screenshots or raw logs are attached because they may contain private workspace information.
- No absolute local paths are included in this report.
Activity
github-actions commentedon Jul 10, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
66Ton99 commentedon Jul 10, 2026
Additional sanitized reproduction:
finish_reason=stop.Request blocked.banner and no assistant response.This suggests that a text-log attachment is one way to trigger the issue, but the persistent failure is more generally tied to inherited/compacted thread state. It may share a root cause with #32028, while this issue additionally covers the thread becoming unusable for subsequent small prompts.
No screenshot, session identifier, raw log, personal information, or local path is included in this comment.
66Ton99 commentedon Jul 10, 2026
Impact update:
For sustained Codex App workflows,
gpt-5.6-solis currently effectively unusable for me because of this bug.Short prompts in new threads may work, but long-running tasks repeatedly reach the broken state where:
Request blocked.;This has reproduced across multiple tasks using
gpt-5.6-sol, including a task that had already compacted successfully and remained well below the reported context-window limit. As a result, the model cannot currently be relied upon for long-running coding tasks in the app.This is a regression compared with
gpt-5.5. In the same Codex App environment, account, and workflow, switching togpt-5.5works normally: tasks and follow-up prompts continue without the persistentRequest blocked.failure. The same workflow becomes unusable withgpt-5.6-sol.The working
gpt-5.5control makes an account-wide authentication, usage-limit, or general connectivity problem less likely and points to a regression in thegpt-5.6-solrequest/context path.ezoushen commentedon Jul 11, 2026
Same here, my workaround for this issue is switching back to GPT-5.5 and do the compact and then switch back to 5.6 for continuing the original works
myleswortham commentedon Jul 11, 2026
Same, and I found @ezoushen's workaround works, but I agree, it makes things unreliable at best. I've had it happen after it was, presumably, thinking for 20 minutes and then in the middle of that, "Request blocked." Sure, I can compact it at that point and reset it to the tune of either waiting another 20 minutes or noticeably worse performance since it doesn't seem like the context from it's 20 minutes of work without output translated to anything in context.
gnmpwr commentedon Jul 12, 2026
Yep, same here. I tried to continue working this morning and caught this bug in one chat. Everything was fine in the evening. I got up in the morning and it's not OK anymore. I didn't do anything unusual. No big documents. I hope guys from OpenAI is aware of this and fix it soon.
myleswortham commentedon Jul 12, 2026
So I can now successfully recreate this issue on command from a new chat with the same prompt. Again, brand new chat, single prompt, all ending in failure.
and my last prompt on why it happens has been... filtered for profanity "Request blocked keeps happening literally every time I ask this question. I have zero idea why. 1 minute, 2 minute, 10 minutes, in the middle, blocked, why?" but here's the response:
And that's also a fresh prompt. The conclusion at the end seems to be potentially telling?
cuipengfei commentedon Jul 12, 2026
Cross-referencing a related finding that may help isolate the trigger.
In can1357/oh-my-pi#5184, we performed marker minimization against Copilot
gpt-5.6-*and found that the specific text string<|channel|>analysisin the input payload is sufficient to trigger:{"error":{"message":"Request blocked.","code":"invalid_request_body"}}Model matrix (same payload, one-shot each):
Not blocked:
<|channel|>alone,<|channel|>final,<|channel|>commentary,<|channel|>reasoning,<|channel|>thinking.This suggests the
gpt-5.6-*backend has an input-side safety classifier that rejects requests containing specific Harmony/ChatML control-token combinations — not just output-side moderation.Your report of compacted thread state triggering
Request blockedcould share this root cause: if the compacted/serialized context contains Harmony analysis-channel markers, those markers would be present in the input payload. It may be worth testing whether your failing threads contain<|channel|>analysisor similar control-token text.Additional note: @myleswortham reported being able to recreate this from a new chat with a single prompt (3/3), which suggests the trigger may not require long compacted history — certain prompt content alone may suffice. If you can share the reproducing prompt, we could test whether it contains control-token-like text patterns.
Related: #32533, #32028.
wiketool commentedon Jul 14, 2026
same, thread id: 019f5fb6-069e-7b21-bb28-d9db3ca8f5f1
rashmibanthia commentedon Jul 20, 2026
I hit this 12 times over 8 days for GPT 5.6 models. Root cause matches mentioned above
My project stores GPT-OSS transcripts which includes harmony format, so source files contain <|channel|>analysis tokens. If Codex reads one of those files into context on gpt-5.6-sol and gpt-5.6-terra, the request is blocked. The same files work normally on gpt-5.5.
bprashanth commentedon Jul 22, 2026
Codex CLI: 0.144.1
Authentication: ChatGPT OAuth
Time: 2026-07-22 13:58:50–14:03:32 UTC
Rollout size: 48,696,373 bytes / 27,489 events
Context compactions: 31
Immediately before the failure, the thread emitted context_compacted.
The next backend request returned HTTP 200, then the stream ended with:
Turn error: Request blocked.
Quota headers reported x-codex-primary-used-percent: 10.
No authentication, sandbox, approval, or transport error occurred.
Subsequent harmless messages in the same thread were also blocked.
Changing model/reasoning settings did not recover the thread.
A new thread on the same account and system succeeded immediately.
The final retry additionally logged:
incremental request failed, items didn't match
unhandled responses event: error
The CLI does not retain or display the backend error category/reason, making
it impossible to distinguish moderation false positive from corrupted
compacted/incremental conversation state.
benvanik commentedon Jul 31, 2026
I believe I just hit this too. My agent was reading the llama.cpp benchmarking corpus and beads that may have contained references to it, and then the entire session got poisoned (no recovery after rewind/resume):

I suspect it hit various sequences that may have looked like prompt injection to a classifier. An analysis reports "Two later rewinds merely appended rollback markers (num_turns: 2, then 5). They did not remove the poisoned records." which would explain why it's still blocked even after rewinding.
The results of this command are what triggered the poison:
So, uh, if you work on llama.cpp beware.
For those who hit this and need to restore a session, here's a workaround:
I recovered a poisoned thread without editing SQLite or modifying the original rollout. This worked with
codex-cli 0.144.0.Locate the rollout by session UUID under
~/.codex/sessions/**/rollout-*<SESSION_ID>.jsonl, then checksum/back it up.Have the recovery agent inspect only JSON structure—line number, record type, role, and byte length. Do not print or attach suspicious message/tool-output contents, or the recovery thread may also be blocked.
Find the last known-good model-visible boundary, ideally a
response_itemassistant message. Copy the complete JSONL prefix through that line into/tmp/safe-prefix.jsonl. Leave the original untouched.Use Codex’s app-server to fork that shadow prefix. Initialize with the experimental API capability, then call:
{"method":"initialize","id":0,"params":{"clientInfo":{"name":"codex_recovery","title":"Codex recovery","version":"1"},"capabilities":{"experimentalApi":true}}} {"method":"initialized","params":{}} {"method":"thread/fork","id":1,"params":{"threadId":"<ORIGINAL_SESSION_ID>","path":"/tmp/safe-prefix.jsonl"}}Feed those as JSONL to:
The
pathparameter lets Codex fork the sanitized prefix into a fresh thread. If the prefix ends mid-turn, Codex adds its canonical interruption marker andturn_abortedevent. It also creates the correct rollout and SQLite metadata, so manual database edits are unnecessary.I first tested this using an isolated temporary
CODEX_HOME. After structural validation, I repeated the fork against the normal Codex home and used the returned thread ID.Finally, smoke-test the recovered thread with a prompt that forbids tools and any suspected source material:
Mine completed successfully and returned
RECOVERED. The original poisoned rollout remained byte-for-byte unchanged.One wrinkle: normal
thread/fork(lastTurnId=...)did not work after UI rewinds because the rollback markers had removed the desired turn from Codex’s effective turn projection. Forking a physical JSONL prefix viapathavoided that problem.SilentBless commentedon Aug 1, 2026
got same, thread id: 019fba89-4f96-7f73-be24-532917e0ca4b
frisco-deng commentedon Aug 6, 2026
I have gotten the same issue on a main thread attempting remote operation and any thread attempting to continue off that previous thread (a total of 5 now).
This is the same failure class as openai/codex #32533
mrinmoyghosal commentedon Aug 8, 2026
same here, its terrible! So the workaround works for me one time is to copy the old session ID after quitting the session. And then ask codex to resume from that ID via prompt. if you run the
codex resume ....command then it doesn't work for me and I get same "Request blocked" but with fresh session with prompting previous id somehow worked.shipiyouniao commentedon Aug 11, 2026
@jif-oai, tagging you because you appear to maintain the affected session/context paths; please redirect me if someone else owns this area.
Reproduction
I reproduced this in a fresh Codex task, so a long pre-existing conversation is not required:
Request blocked.A second fresh task fetched the same issue set through
gh apiand exposed only bounded structured metadata; it completed successfully. This suggests that some tool-output content or combinations can trigger the service safeguard. Long sessions amplify the problem, but are not the only trigger.Client-side root cause
The initial safeguard decision appears to be service-side. The client bug is what happens afterward: the rejected turn's user input, tool outputs, and partial model output remain model-visible and are resent on every later prompt, permanently poisoning the conversation.
A rejected sampling request should behave like an uncommitted model-context transaction:
Otherplus the exactRequest blocked.message.Prototype
I implemented that behavior in this commit:
shipiyouniao@d0d4f1d
It includes:
The relevant protocol, reconstruction, and mocked Responses API tests pass locally.
Related reports and scope
This directly targets the session-poisoning behavior in #32177. It may also mitigate the permanently-unusable-session symptom in #31820, #32028, and #32533, but those reports have distinct image-limit or compaction triggers. #33103 looks like an initial safeguard false positive: this prototype preserves session usability after rejection, but does not alter or bypass the safeguard itself.
External PRs are invitation-only, so I am sharing the analysis and prototype here first. If this approach matches the intended session semantics, I would be happy to open an invited PR or adjust the design before doing so.
ooiuuii commentedon Aug 13, 2026
I can reproduce the cross-task poisoning behavior on Codex desktop for Windows
26.803.10989.0.This is not just a single long task becoming non-resumable. A fresh investigation task worked normally for multiple turns, then consumed material from affected task histories while gathering diagnostics. That investigation task subsequently failed with the same generic error, and its immediate retry failed again:
019ffb57-cf5b-7a30-9b54-11700d96569c019ffb8a-2fa1-70d0-9ce4-5a0ebe5767a5:308800 ms019ffb8f-75bc-7a92-84ff-4e3a35335a0e:4073 msRequest blocked.withcodex_error_info: other62193input tokens with a258400context window49%;rate_limit_reached_type=nullI now have four affected tasks across an original long-running task, takeover/recovery tasks, and this evidence-building task:
019fb116-436b-7781-9dae-e1a8b8ad71de1042605934 ms019ffb28-4ac3-7981-90d5-009f0c55c6f51754285883 ms019ffb51-d54d-77a2-8b95-8e67a6d1a2b3889183275 ms019ffb57-cf5b-7a30-9b54-11700d96569c621934073 msMinimal follow-up prompts in affected tasks do not recover them. All four remained below the
258400context window and none recordedrate_limit_reached_type. The Windows desktop log exposes only the local App Serverturn/startIPC request ID; it does not expose a backend request ID, HTTP status, or rejection category.The evidence is consistent with this issue and also overlaps #33973 and #35160. I am intentionally not attaching raw rollout JSONL because it contains private project content and may contain the material that triggers the rejection. I can provide maintainers with a redacted allowlist extraction containing timestamps, task/turn IDs, token counts, context window, rate-limit state, durations, and hashes.
Two recovery features would materially reduce impact even before the underlying rejection is fixed:
other;