Codex CLI persists malformed tool_search_call arguments, causing 400 property_name_above_max_length on resume
Open 💬 12 comments Opened Jun 4, 2026 by volveezz
What version of Codex CLI is running?
0.137.0
What subscription do you have?
Pro
Which model were you using?
gpt-5.5
What platform is your computer?
Linux 6.6.87.2-microsoft-standard-WSL2 x86_64 unknown
What terminal emulator and version are you using (if applicable)?
WSL
What issue are you seeing?
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "[ObjectParam] [input[55].arguments.>'+ennialsf\u00f3lnub etsennialsreti\u05e2\u05e0\u05d8\u05e9apie \u0440\u044b\u0448iv\u00e9playerschuheNegotiishe \u0906\u092f\u094b\u091c
Tapelade\u0639\u062f\u064a\u0646ta\u00e7\u00e3onubwriter/cop HarrietenciamentobotsJuan meigeria rezSED\u0430\u043b\u0430\u043croch pencilsretipleados\u0434\u0435\u043d\u0438\u0435\u043c Nyereit Bots Bulk
Pantryasinoi\u00e3o.Generic_fillfinder\u043d\u0443\u0446\u044c Rasullaug\u043b\u0435\u0439_STAolfasetreit Streit Nou Dee Preston/legast\u00e1naFABj\u00e4nendenteJason Argentbots ETS opts th\u01b0\u1edfng
ballot frustratingnthestrian uncertainties eyeb Kerryhtarething\u6765\u770bbotAllocatornyamaWrite\u05dc\u05d9\u05eanub\u043f\u043b\u044f sach.zaxxer\u043f\u0430\u0440\u0430\u0442/be TachPur \u9999\u6e2fLaugh
konkurr el\u00e9trACLEolf globaleenant_ls\u10d5\u10d8\u10d3 setsreit leastelassen\u00fcssURITY \u0645\u0639\u0646gahretilish Ball\u2019abandil\u00f3st\u00e6Substring\u0941\u092anub \u0440\u0430\u0434\u0443
interferlanders\u0441\u0435\u043d\u0434\u0456 s\u00f8ger \u5927\u53d1\u5feb\u4e09\u5b98\u7f51 j\u00e9g\u00ebriszendstylesbotu cari hinkwaswo\u0443\u0441\u044b\u043b\u0430\u0440\u04b5\u04d9vidorsections/
Subthreshold\u0525\u0448\u044cdaawriteatillugu \u5927\u53d1\u5feb\u4e09\u5982\u4f55\u0445\u044b\u04b5
\u04bb\u04d9\u0440\u0431\u0438\u0439retry_Botsthroughoutfilebancookies\u04bf\u043a\u0430itaatspu\u0430\u04e1\u0430\u0440\u0430 Bruins\u5f69\u7968\u7f51\u5740pythonrit] [property_name_above_max_length] Invalid
property name in 'input[55].arguments': '>'+...rit' is too long. Expected a string with maximum length 256, but got a string with length 806 instead."
},
"status": 400
}
What steps can reproduce the bug?
Uploaded thread: 019e9232-51e7-7051-89ac-9fca142e3b3d
What is the expected behavior?
_No response_
Additional information
_No response_
12 Comments
I hit the same failure class and was able to recover the affected session by editing the persisted rollout JSONL. Adding details in case they help narrow the bug.
Environment:
0.137.00.130.00.137.0, so upgrading alone did not repair the affected session.7.0.9-205.fc44.x86_643.6agpt-5.5Observed behavior:
codex resume <thread-id>failed repeatedly with an API 400 shaped like:Local transcript diagnosis:
response_item/tool_search_call..payload.argumentswas an object with a single garbage property key instead of the expected argument shape.tool_search_callrecords in the same rollout file:708566tool_search_callwas followed by afunction_call_outputwith:Recovery that worked:
tool_search_callrecord.function_call_outputrecord.token_countevent for that failed tool call..payload.argumentsobject keys longer than 256 chars.tool_search_callblock the same way.The practical jq diagnostic I used was:
Hypothesis:
Codex can persist malformed
tool_search_call.payload.argumentsafter tool argument parsing fails. On resume, the persisted transcript is replayed into the API request, and the API rejects the oversized object key before the model can continue. The resume path probably needs to sanitize/drop invalid historical tool calls, or the persistence path should avoid writing malformed tool-call items after argument parsing fails.I hit the same failure class in Codex Desktop, not just CLI resume.
Observed behavior:
Notable details:
input[293].arguments1709This suggests the bug is broader than just a CLI resume edge-case:
If helpful, I can add more reproduction context later, but I wanted to confirm this exact
property_name_above_max_lengthpattern is also happening in Desktop withinput[293].arguments.I hit the same failure class on Codex CLI and was able to narrow one occurrence down to the raw Responses websocket event, before rollout JSONL replay.
Environment:
0.139.0gpt-5.56.17.0-1016-oracleonaarch64codex-tuiWhat I observed:
tool_search_callresponse items.query/limit.arguments:The immediately following rollout item was:
Additional evidence from
~/.codex/logs_2.sqlite:2026-06-16T09:04:39Z:stream disconnected - retrying sampling request (3/5 in 733ms)...2026-06-16T09:04:41Z: websocket reconnect succeeded for/responses2026-06-16T09:04:49Z: raw websocket eventresponse.output_item.addedfor the same item/call id:2026-06-16T09:05:30Z: raw websocket eventresponse.output_item.donefor the same item/call id contained the malformed 2503-character property name inarguments.Code path that matches the transcript:
codex-rs/protocol/src/models.rs:ResponseItem::ToolSearchCall.argumentsis a rawserde_json::Value.codex-rs/core/src/tools/router.rs:ToolRouter::build_tool_calldeserializes that value intoSearchToolCallParams { query, limit }, which fails withmissing field query.codex-rs/core/src/stream_events_utils.rs: theFunctionCallError::RespondToModelpath records a genericfunction_call_outputwithcall_id: String::new().Tool search output is missing for call id: call_0arIzewv9N3HEFLA8hQMNZ5oand synthesizes an emptytool_search_outputon later requests.My current hypothesis:
ToolRouter::build_tool_callbecause the completed Responses websocket item already contains it.tool_search_callparse failures are recorded as an orphanfunction_call_outputwith an emptycall_idinstead of atool_search_outputtied to the originalcall_id.tool_search_call.arguments, andtool_search_callitems preservecall_idand do not poison persisted history/resume.Potential client-side fix shape, if maintainers agree:
tool_search_callwith invalidarguments.ToolCallis built, preserve the originalcall_idand record/respond with atool_search_outputsuch astools: [](or another structured error shape the Responses API accepts fortool_search) instead offunction_call_output { call_id: "" }.tool_search_callitems whoseargumentsare not shaped likeSearchToolCallParams, to avoid laterproperty_name_above_max_lengthreplay failures.I have a small client-side hardening patch prepared for the second part above: it preserves the original
tool_search_call.call_idand records atool_search_outputinstead of an orphanfunction_call_output { call_id: "" }when clienttool_searchargument parsing fails.The local patch is intentionally narrow:
tool_search_call.argumentsgit diff --check: passcargo fmt -- --config imports_granularity=Item --check: passjust test -p codex-core handle_output_item_done_preserves_tool_search_call_id_for_invalid_arguments: passIf this direction matches what the Codex team wants, would you be open to inviting an external PR for this focused client-side fix? I will hold off on opening a PR unless invited, per
docs/contributing.md.Resume should validate persisted tool-call envelopes before replay. If a tool_search_call has malformed arguments, keep the original call id, attach a parse_error record, and emit a matching tool_search_output or repairable skip event. The session should never serialize an orphan output with an empty call id and then fail the whole resume request.
---
_Generated with ax._
I hit what looks like the same issue on Codex CLI
0.142.3usinggpt-5.5withxhighreasoning.Sanitized sequence from local logs:
tool_search_callwhoseargumentsobject did not contain the requiredqueryfield.argumentscontained a single generated/gibberish multilingual property name with length6585, value173.call_id:I also saw normalization warnings consistent with poisoned replay state:
This was Codex CLI, not Desktop. Auth/websocket connection appeared healthy, and continuing in a fresh thread worked. The issue seems to be that an invalid internal
tool_search_callcan be persisted after compaction and then poisons future session replay.For those still hitting tool-calling issues (namespace doubling, broken HTML rendering): before rolling back to 0.142.5, check whether your install is actually complete.
My symptoms matched what's being reported here, but the root cause turned out to be a missing platform binary —
@openai/codex-linux-x64— not a version regression. The globalnpm install -ghad silently skipped the optional dependency, leaving an incomplete install regardless of version.Fix (Linux x64):
That installs
codex-linux-x64into the correct nested location. Currently running 0.143.0 without issue — tool calls passing, HTML rendering correctly.Independent confirmation from an application embedding
@openai/codex-sdk/ Codex0.143.0.The failure sequence matches this issue:
response_itemwhose payload type wastool_search_call.argumentsobject contained a generated property name longer than 256 characters (985 characters in the observed case).400 invalid_request_error,property_name_above_max_length, atinput[36].arguments.The important inconsistency is that Codex can emit/persist a response item that the API will not accept when that same item is replayed as input. This permanently poisons resume for the session unless the client validates the rollout or discards/repairs the invalid item.
A sanitized downstream workaround is to:
Expected upstream behavior: Codex should not persist unreplayable tool-call items, or the resume path should validate/sanitize them before sending history back to the API. No malformed property name or customer/session identifiers are included here.
Independent confirmation with a newer CLI and a remote-compaction failure mode.
Environment:
0.144.60.145.0gpt-5.5, reasoningxhighremote_compaction_v2enabledThe original rollout contains two malformed
tool_search_callresponse items. Eachargumentsobject has a single generated multilingual/gibberish property key instead ofquery; the key lengths are 538 and 1082. The calls were persisted with call IDs, while the following parse-failure outputs have empty call IDs.After that, every prompt emitted a remote compaction 400 at
input[294].argumentswithproperty_name_above_max_length(maximum 256, observed 538). Forking the affected thread did not recover it: the new 0.145.0 fork inherited the poisoned history and failed the same way. A fresh thread with a manual handoff works.Additional data points:
2026-07-25T20:03:20Zand2026-07-25T20:04:42Z019f76b7-afbe-7fe3-b4f5-492eb44ef059019f9af1-f0f3-7c92-aa41-e132c8765f4cNo prompt or repository content is included here. This confirms that upgrading/forking does not sanitize the invalid historical item and that it can permanently break automatic remote compaction, not only explicit resume.
Same failure class here, and I can add two things this thread is missing: it reproduces on the first-party Responses API with no gateway in front of it, and I have per-model rates from a production dataset showing it is ~40x worse on gpt-5.6 than gpt-5.5.
Environment
https://api.openai.com/v1/responses— first-party, no proxy, no Azure/Bedrockgpt-5.6-terra,gpt-5.6-solstrict: true, reasoning effort medium/highVariant 1: arguments exceed the limit the same API enforces
A single tool call was emitted with 1,126,633 characters of
arguments— one array element repeated tens of thousands of times:The core issue, same as this ticket: the model emits an
argumentsstring that the same API then refuses to accept. Generation and validation disagree.And as reported here, it is unrecoverable rather than transient. The output is persisted as conversation history, so every later request in that conversation replays it and gets the identical 400. Three such calls landed in one conversation (1,126,633 / 1,062,179 / 751,153 chars) and it could never make progress again. Recovery is impossible client-side without rewriting the model's own recorded output.
Variant 2: chat-template scaffolding and glitch tokens inside
argumentsThis is the part that matches the "garbled Unicode and mixed-language text" in the original report, and it looks like more than encoding noise. A 32,603-char call contained, inside the
argumentsJSON:to=functions.glob,to=functions.read_file,ChatGPT to=functions.glob— channel/routing syntax appearing as argument content<|DELIM_nT5|>,】【。system,】【。assistant,+#+#+#+#+#+assistant彩神争霸,天天中彩票, plus Thai, Armenian and Georgian fragmentsThe model appears to notice its output is malformed and attempts to recover by re-emitting tool calls inline as text, which extends the corruption instead of ending it.
This variant is usually under the size limit, so it parses and executes. One built a
findwith 815-nameclauses and returned normally. No error surfaced anywhere — silent corruption, which is worse than the 400.Measured incidence
Every tool call in our production database, matched on the markers above:
| Model | Tool calls | Degenerate | Rate | First seen |
|---|---:|---:|---:|---|
| gpt-5.6-terra | 5,035 | 45 | 0.89% | 14 Jul 2026 |
| gpt-5.6-sol | 592 | 4 | 0.68% | 20 Jul 2026 |
| gpt-5.5 | 9,533 | 2 | 0.021% | 15 Jun 2026 |
| gpt-5.4 | 14,936 | 1 | 0.007% | 14 May 2026 |
It was present from our first day of using
gpt-5.6-terra(14 Jul 2026), which suggests it is inherent to the release rather than a later regression.Caveats, so nobody over-reads the numbers: this is not a controlled comparison — reasoning-effort mix and prompts varied over the period — and events cluster per conversation (27 of the 45 came from one conversation), so the rate is not an independent per-call probability. Once a conversation degenerates it tends to keep degenerating. The directional gap is large enough that volume alone does not explain it, and 4,383 calls on another vendor's model with zero hits is a useful null.
The persisted
tool_search_call.argumentscorruption here is a strong recovery test: the rollout remains readable, but replay is permanently rejected because a malformed property name was saved into history.Codex Rescue
0.1.0a3has proven handling for some corrupted tool-call metadata, but not arbitrary argument-shape failures. I’m trying to validate whether its current diagnostic boundary catches this safely. It will not delete those records, guess the intended query, or modify the original rollout; recovery remains fail-closed.If you still have a pre-edit copy, would you try:
Sanitized output is sufficient—please don’t share the raw JSONL, prompts, repository contents, DBs, credentials, or private paths.
https://github.com/shleder/codex-rescue
I hit the same failure mode in a long-running Codex chat using codex-cli 0.147.0 on Linux x86_64. Remote compaction returned HTTP 400 with property_name_above_max_length for input[294].arguments: the malformed property name was 538 characters (maximum 256) and consisted of apparently generated multilingual/random tokens. After the first occurrence, every subsequent prompt in that thread emitted the same remote compact error, so the thread could not recover in place. Moving the task to a new chat via a handoff restored normal operation. I am not attaching the original thread because it contains private infrastructure context, but the stable details are: remote compact task, status 400, input[294].arguments, expected max 256, observed 538. This appears consistent with malformed tool-call arguments being persisted into the compaction input rather than a user-authored property name.