You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Blocking stop hook continuation can fail with invalid local message id #20783
A blocking stop hook can break the Codex turn instead of prompting Codex to fix the blocked condition.
Observed failure:
{
"error": {
"message": "Invalid 'input[118].id': 'c047686e-8eaf-4c21-9eba-e25d3122d898'. Expected an ID that begins with 'msg'.",
"type": "invalid_request_error",
"param": "input[118].id",
"code": "invalid_value"
}
}
Why this matters
A stop hook with decision: "block" is supposed to inject a continuation prompt, for example telling Codex to fix failing lint/type/test checks before stopping.
In this failure mode, the stop hook successfully blocks and emits the continuation prompt, but the next Responses API request rejects the conversation input. That makes the hook mechanism counterproductive: it prevents Codex from continuing to fix the problem.
Expected behavior
When a stop hook blocks, Codex should append the hook continuation prompt and continue the turn normally.
Actual behavior
Codex sends a locally generated UUID as input[].id for a message item. The Responses API rejects it because message ids must be server-generated msg... ids.
Root-cause hypothesis
build_hook_prompt_message creates a user message with a local UUID. Later, attach_item_ids reattaches hidden item ids into the serialized Responses API request body.
That path appears to treat local message UUIDs the same as server-generated message ids, so a local UUID is sent as a wire message.id.
Indexed this hook ticket in the umbrella tracker: #21753
Goal: collect the scattered Codex hook requests and bugs into one parity matrix for Full Claude Code Hook Parity (29+), while preserving this issue as the detailed thread for its specific behavior.
I believe this has the same root cause as #27928: a local Codex-generated message ID is replayed into input[].id, and Azure Responses rejects it because message IDs must begin with msg.
I verified a local patch that strips non-msg* IDs only for ResponseItem::Message before Responses API requests, while preserving server message IDs and non-message item IDs.
@pakrym-oai this fix addresses both #20783 and #27928. Refrained from raising a PR per the repo guidelines, but happy to raise one if it would be accepted?
Additional local reproduction on Codex Desktop 26.707.31428 (CLI 0.144.0-alpha.4):
A Stop hook injected a user hook_prompt after a turn that edited files.
The local rollout persisted that prompt as a Responses message with a locally generated UUID in message.id, rather than a server-generated msg... ID.
A later compaction retained the same UUID in replacement_history.
After resuming the thread, every follow-up failed before model output with ApiIdParam / invalid_id_prefix because that local UUID was serialized as input[6].id.
The UUID is not the thread/conversation ID and the user did not supply it through an API request. This reproduces the failure from an ordinary Desktop session with a Stop hook enabled.
This supports guarding both persistence/replay paths: do not retain a local UUID as a wire message.id; and only attach a message ID to a Responses request when it is a server-generated msg... ID. No local paths, thread IDs, or archived conversation contents are included here.
Confirming this on the direct OpenAI path (stock provider config, ChatGPT-account auth — no Azure involved): a Stop hook returning {"decision":"block","reason":"…"} permanently wedged a session in the Codex macOS app.
What the session rollout shows: the block reason was recorded into history as a user message item wrapped in <hook_prompt hook_run_id="stop:2:…">, carrying a locally generated bare UUIDv7 id (019f4da5-72da-7671-b599-b3cd3b157b40 — no type prefix). Every subsequent request replayed that item and was rejected:
Invalid 'input[0].id': '019f4da5-72da-7671-b599-b3cd3b157b40'. Expected an ID that begins with 'msg'.
We saw the same rejection hours apart (input[0].id, later input[97].id) as the conversation grew. The session never recovered and had to be abandoned — so beyond breaking the continuation turn (the OP's case), a Stop-hook block poisons persisted history: every later turn fails, which in practice is permanent session loss. Notably it is not deterministic: another long-running session on the same machine absorbed five identical stop hook injections (same <hook_prompt> shape, same bare-UUIDv7 ids in the rollout) without failing, including across compaction and resume — so the rejection appears to depend on when/whether the locally-generated id gets reattached on replay. We've disabled decision:block on Codex entirely until this is fixed.
Environment: macOS (arm64, Darwin 25.5.0), Codex macOS app; codex --version on the same machine reports codex-cli 0.131.0; model gpt-5.6-terra. #32282 looks like another manifestation of the same class.
I can reproduce this in Codex Desktop on Windows, and in my case it is also triggered by a hook.
Hook feedback
[ApiIdParam] [input[0].id] [invalid_id_prefix]
Invalid 'input[0].id': '019f5eaa-4fa9-70d1-9d35-a6b2fbdcae81'.
Expected an ID that begins with 'msg'.
The rejected value is a locally generated UUID from the hook-generated message, not a server-generated msg... ID.
This appears consistent with the root cause described in this issue: a hook continuation message is persisted with a local UUID, and that UUID is later reattached as a Responses API input[].id.
Additional reproduction after the latest macOS desktop update:
Product: Codex Desktop for macOS
App version: 26.707.71524, build 5263
Bundled CLI: codex-cli 0.144.2
Trigger: global Stop hook returning {"decision":"block","reason":"..."}
Loop guard: when stop_hook_active is true, the hook returns {"continue":true}
Result: the generated continuation fails with ApiIdParam / invalid_id_prefix because a local UUID is sent as input[].id where a server-generated msg... ID is required
Scope: reproduced in fresh threads because the Stop hook is global
Timing: this hook worked before the desktop update and began failing after the update
The same invalid-ID class also appears in local desktop logs during ambient_suggestions refresh, which suggests the item-ID serialization/replay problem is broader than only parsing the Stop hook result. The blocking Stop hook reliably exposes it by creating a continuation message.
No local paths, thread IDs, full UUIDs, or conversation contents are included here.
Verified on 2026-07-14 against current main d7ba5ff and parent 08ba14b of #32312. A focused Azure/store request test added two hook-prompt user messages with the same synthetic bare UUID, representing persisted history and compaction replacement_history. At the parent, both IDs remained on the outbound request and the omission assertions failed (0 passed, 1 failed). On current main, the same test passes (1 passed, 2978 skipped): request preparation removes any response-item ID that is not prefixed before the store/item-IDs early return, covering legacy history on HTTP and WebSocket paths.
This confirms that the serializer/replay root cause reported here is resolved in source by #32312 (merge c9d52de); a duplicate patch or report is not needed. The installed Codex Desktop 26.707.71524 still bundles codex-cli 0.144.2 and reproduced the bare-UUID hook-prompt poison in a disposable task today. The remaining upstream delivery gap is a Desktop build that contains c9d52de. Standalone CLI 0.144.4 resume can process the poisoned disposable history, but that does not repair the older Desktop app-server loaded context.
Confirming this is now reproducible in the new ChatGPT desktop app's Codex mode with a configured hook.
Observed behavior
The hook workflow was working normally through July 13, 2026.
Beginning overnight July 13–14 (America/New_York), when the hook fires the Desktop thread fails with:
[ApiIdParam] [input[0].id] [invalid_id_prefix] Invalid 'input[0].id': '019f611a-958f-7621-88bb-eede86b646d4'. Expected an ID that begins with 'msg'.
The affected thread is effectively unusable in Desktop after this occurs; subsequent attempts cannot continue normally.
The same thread can be resumed through Codex CLI when hooks are disabled for that invocation, which points to the Desktop hook persistence/replay path rather than corruption of the underlying task.
This appears consistent with the Desktop regression tracked in #32282, but the hook firing is the direct trigger in this reproduction. Because hooks are part of the normal workflow, this is currently blocking practical use of the Desktop app rather than being an intermittent cosmetic error.
App/OS version and a sanitized hook definition can be added if maintainers identify the preferred diagnostics or log location.
Invalid 'input[57].id': '<local-uuid>'. Expected an ID that begins with 'msg'.
After this happens, every subsequent prompt in the same thread returns the same error, making the thread permanently unusable. A structured scan of local rollout logs found multiple Stop-hook-generated hook_prompt messages whose message ids were UUIDs rather than server-generated msg_ ids.
As a project-side workaround, I changed the Stop hook from decision:block to advisory decision:allow while preserving the review-required marker. I added a regression test that creates an isolated Git repository, triggers the real review marker and Stop hook, and verifies that the marker remains while the Stop decision is allow. The failure has not reproduced through that path since.
This appears to be the same local-message-id / attach_item_ids root cause described here and is also related to #27928.
Activity
kaydash commentedon May 5, 2026
저도 이 오류를 계속 겪습니다. ms azure ai foundry에 배포된 gpt-5.5 모델은 response api로만 서빙되며, 이것을 연결해서 사용하는중에 자주 발생하고있어요. opencode + omo 에서는 이런오류를 겪지않는데말이죠.
shawnsw commentedon May 6, 2026
Similar situation, I'm also using Azure AI Foundry, model gpt-5.5. Unsure if this is only reproducible with Foundry.
oxysoft commentedon May 8, 2026
Indexed this hook ticket in the umbrella tracker: #21753
Goal: collect the scattered Codex hook requests and bugs into one parity matrix for Full Claude Code Hook Parity (29+), while preserving this issue as the detailed thread for its specific behavior.
AdithyanI commentedon May 29, 2026
I confirm I see the same issue when using the model from Azure AI Foundry.
shawnsw commentedon May 31, 2026
Do you see the same with direct OpenAI model API? Haven't tested that myself.
shawnsw commentedon Jul 7, 2026
I believe this has the same root cause as #27928: a local Codex-generated message ID is replayed into
input[].id, and Azure Responses rejects it because message IDs must begin withmsg.I verified a local patch that strips non-
msg*IDs only forResponseItem::Messagebefore Responses API requests, while preserving server message IDs and non-message item IDs.More details in #27928:
#27928 (comment)
My verified branch:
https://github.com/shawnsw/codex/tree/fix/responses-local-message-ids
@pakrym-oai this fix addresses both #20783 and #27928. Refrained from raising a PR per the repo guidelines, but happy to raise one if it would be accepted?
doudouOUC commentedon Jul 11, 2026
Additional local reproduction on Codex Desktop 26.707.31428 (CLI 0.144.0-alpha.4):
hook_promptafter a turn that edited files.messagewith a locally generated UUID inmessage.id, rather than a server-generatedmsg...ID.replacement_history.ApiIdParam/invalid_id_prefixbecause that local UUID was serialized asinput[6].id.The UUID is not the thread/conversation ID and the user did not supply it through an API request. This reproduces the failure from an ordinary Desktop session with a Stop hook enabled.
This supports guarding both persistence/replay paths: do not retain a local UUID as a wire
message.id; and only attach a message ID to a Responses request when it is a server-generatedmsg...ID. No local paths, thread IDs, or archived conversation contents are included here.jaymcampbell commentedon Jul 11, 2026
Confirming this on the direct OpenAI path (stock provider config, ChatGPT-account auth — no Azure involved): a Stop hook returning
{"decision":"block","reason":"…"}permanently wedged a session in the Codex macOS app.What the session rollout shows: the block reason was recorded into history as a user
messageitem wrapped in<hook_prompt hook_run_id="stop:2:…">, carrying a locally generated bare UUIDv7id(019f4da5-72da-7671-b599-b3cd3b157b40— no type prefix). Every subsequent request replayed that item and was rejected:We saw the same rejection hours apart (
input[0].id, laterinput[97].id) as the conversation grew. The session never recovered and had to be abandoned — so beyond breaking the continuation turn (the OP's case), a Stop-hook block poisons persisted history: every later turn fails, which in practice is permanent session loss. Notably it is not deterministic: another long-running session on the same machine absorbed five identicalstophook injections (same<hook_prompt>shape, same bare-UUIDv7 ids in the rollout) without failing, including across compaction and resume — so the rejection appears to depend on when/whether the locally-generated id gets reattached on replay. We've disableddecision:blockon Codex entirely until this is fixed.Environment: macOS (arm64, Darwin 25.5.0), Codex macOS app;
codex --versionon the same machine reportscodex-cli 0.131.0; modelgpt-5.6-terra. #32282 looks like another manifestation of the same class.null0526 commentedon Jul 14, 2026
I can reproduce this in Codex Desktop on Windows, and in my case it is also triggered by a hook.
Hook feedback
[ApiIdParam] [input[0].id] [invalid_id_prefix]
Invalid 'input[0].id': '019f5eaa-4fa9-70d1-9d35-a6b2fbdcae81'.
Expected an ID that begins with 'msg'.
The rejected value is a locally generated UUID from the hook-generated message, not a server-generated msg... ID.
This appears consistent with the root cause described in this issue: a hook continuation message is persisted with a local UUID, and that UUID is later reattached as a Responses API input[].id.
Environment:
Product: Codex Desktop
Platform: Windows x64
Trigger: hook feedback / hook continuation
Authentication: ChatGPT subscription
I have not verified a fix or workaround yet. This report only confirms another reproduction of the same failure path.
sh-inv commentedon Jul 14, 2026
Additional reproduction after the latest macOS desktop update:
{"decision":"block","reason":"..."}stop_hook_activeis true, the hook returns{"continue":true}ApiIdParam / invalid_id_prefixbecause a local UUID is sent asinput[].idwhere a server-generatedmsg...ID is requiredThe same invalid-ID class also appears in local desktop logs during
ambient_suggestionsrefresh, which suggests the item-ID serialization/replay problem is broader than only parsing the Stop hook result. The blocking Stop hook reliably exposes it by creating a continuation message.No local paths, thread IDs, full UUIDs, or conversation contents are included here.
drastawi commentedon Jul 14, 2026
Verified on 2026-07-14 against current main d7ba5ff and parent 08ba14b of #32312. A focused Azure/store request test added two hook-prompt user messages with the same synthetic bare UUID, representing persisted history and compaction replacement_history. At the parent, both IDs remained on the outbound request and the omission assertions failed (0 passed, 1 failed). On current main, the same test passes (1 passed, 2978 skipped): request preparation removes any response-item ID that is not prefixed before the store/item-IDs early return, covering legacy history on HTTP and WebSocket paths.
This confirms that the serializer/replay root cause reported here is resolved in source by #32312 (merge c9d52de); a duplicate patch or report is not needed. The installed Codex Desktop 26.707.71524 still bundles codex-cli 0.144.2 and reproduced the bare-UUID hook-prompt poison in a disposable task today. The remaining upstream delivery gap is a Desktop build that contains c9d52de. Standalone CLI 0.144.4 resume can process the poisoned disposable history, but that does not repair the older Desktop app-server loaded context.
tadeumaia commentedon Jul 14, 2026
Same problem been happening to be , breaking a lot of long threads
019f6020-9870-7130-b4a7-19d4bfd377d7
yeahjack commentedon Jul 14, 2026
Additional affected Codex Desktop session ID:
019f12d2-590c-7941-9c82-73869d5c7357.Vyzerythe commentedon Jul 14, 2026
Confirming this is now reproducible in the new ChatGPT desktop app's Codex mode with a configured hook.
Observed behavior
This appears consistent with the Desktop regression tracked in #32282, but the hook firing is the direct trigger in this reproduction. Because hooks are part of the normal workflow, this is currently blocking practical use of the Desktop app rather than being an intermittent cosmetic error.
App/OS version and a sanitized hook definition can be added if maintainers identify the preferred diagnostics or log location.
jisi71 commentedon Jul 15, 2026
I reproduced this issue twice in Codex Desktop on macOS.
Environment:
codex-cli 0.136.0.codex/hooks.jsonThe Stop hook returned a blocking decision:
{"decision":"block","reason":"Code files changed but review is still required..."}Codex then stored the generated hook prompt as a local user message with a UUID-style id:
{"type":"message","role":"user","id":"<local-uuid>","content":[{"type":"input_text","text":"<hook_prompt ...>...</hook_prompt>"}]}A later request failed with:
After this happens, every subsequent prompt in the same thread returns the same error, making the thread permanently unusable. A structured scan of local rollout logs found multiple Stop-hook-generated
hook_promptmessages whose message ids were UUIDs rather than server-generatedmsg_ids.As a project-side workaround, I changed the Stop hook from
decision:blockto advisorydecision:allowwhile preserving the review-required marker. I added a regression test that creates an isolated Git repository, triggers the real review marker and Stop hook, and verifies that the marker remains while the Stop decision isallow. The failure has not reproduced through that path since.This appears to be the same local-message-id /
attach_item_idsroot cause described here and is also related to #27928.