Regression after #34645: proxied Azure Responses provider sends item IDs with store=false and fails with "Item with id ... not found"
What version of Codex CLI is running?
codex-cli 0.146.0-alpha.3.1
What subscription do you have?
ChatGPT Pro; the affected Codex Desktop task uses a custom enterprise model provider backed by Azure OpenAI.
Which model were you using?
gpt-5.5
What platform is your computer?
Darwin 25.3.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
iTerm2
Codex doctor report
not available
What issue are you seeing?
Summary
Codex Desktop fails during multi-turn tool use when configured with a custom Responses provider that forwards to Azure OpenAI through a local proxy.
After #34645 ("Always assign response item IDs"), Codex no longer has a supported request shape for this provider topology. The local proxy hides the final Azure hostname from Codex, so Codex does not recognize the provider as Azure and sends:
{
"store": false,
"input": [
{
"type": "reasoning",
"id": "rs_REDACTED",
"encrypted_content": "REDACTED"
}
]
}
The upstream returns:
Item with id 'rs_REDACTED' not found. Items are not persisted when `store` is set to false. Try again with `store` set to true, or remove this item from your input.
Behavior before #34645
With Codex 0.145.0 and the default item_ids = false behavior:
| Provider/request mode | store | Outbound input item IDs | Result |
|---|---:|---:|---|
| Custom provider through local proxy | false | Omitted | Succeeds |
| Provider detected as Azure | true | Included | Succeeds |
When store was false and item IDs were disabled, prepare_response_items_for_request() removed all outbound input[].id values.
Behavior after #34645
Starting with 0.146.0-alpha.1:
| Provider/request mode | store | Outbound input item IDs | Result |
|---|---:|---:|---|
| Custom provider through local proxy | false | Included | Fails |
| Provider detected as Azure | true | Included | Succeeds |
The item_ids feature is now marked as removed/default-enabled, and item_ids = false is accepted only as a compatibility no-op. At the same time, store is still determined only by:
store: provider.is_azure_responses_endpoint()
Therefore, a custom provider behind a local proxy cannot:
- Restore the previous
store=falseplus no outbound item IDs behavior; or - Explicitly request
store=truewithout changing or spoofing the provider name.
Confirmed workaround
Changing only the custom provider display name from:
name = "proxy"
to the exact value:
name = "azure"
causes is_azure_responses_endpoint() to return true. Codex then sends store=true while preserving the same rs_... item IDs, and the same multi-turn tool-call task succeeds.
This confirms that the model, tool call, item ID, encrypted reasoning content, proxy, and upstream credentials are valid. The failure is caused by the unavailable request-shaping combination.
What steps can reproduce the bug?
- Configure Codex Desktop with a custom Responses provider whose local URL forwards to Azure OpenAI:
```toml
model = "gpt-5.5"
model_provider = "proxy"
[model_providers.proxy]
name = "Proxy"
base_url = "http://127.0.0.1:PORT/v1"
wire_api = "responses"
[features]
item_ids = false
```
The proxy is a transparent forwarder. Replace PORT with the local port. Authentication configuration is omitted here.
- Fully quit and restart Codex Desktop so the embedded runtime reloads the provider configuration.
- Start a new Codex task.
- Use a prompt that reliably creates both a reasoning item and a function call:
``textprintf codex-item-id-test
First reason carefully and compute 17*23+19. Then use the terminal to run . Finally reply with the calculation result and terminal output. Do not use other tools.``
- Observe the follow-up
/v1/responsesrequest after the terminal result is returned. It contains:
``json``
{
"store": false,
"input": [
{
"type": "reasoning",
"id": "rs_REDACTED",
"encrypted_content": "REDACTED"
},
{
"type": "function_call",
"id": "fc_REDACTED",
"call_id": "call_REDACTED"
},
{
"type": "function_call_output",
"id": "fco_REDACTED",
"call_id": "call_REDACTED"
}
]
}
- The upstream returns HTTP 400:
``textstore
Item with id 'rs_REDACTED' not found. Items are not persisted when is set to false.``
- Fully quit Codex Desktop and change only the provider name to:
``toml``
name = "azure"
- Restart Codex Desktop, start a new task, and repeat the same prompt.
- The request now contains
store=true, preserves the same item types and IDs, and succeeds.
What is the expected behavior?
A custom Responses provider should be able to declare its upstream storage and request-shaping behavior without relying on provider display-name or base-URL detection.
Minimal compatibility option
The smallest compatibility change may be to keep #34645's internal stable item IDs while restoring features.item_ids = false only as an outbound serialization control.
In other words:
- Codex would continue assigning and retaining stable IDs internally for history, streaming, fork, resume, and compaction.
- When
store=falseanditem_ids=false, Codex would omit only the top-levelinput[].idfields from the serialized request. - When
store=true, IDs would still be serialized regardless ofitem_ids=false, preserving the existing Azure stored-response behavior.
The resulting behavior would be:
| store | item_ids | Outbound input[].id |
|---:|---:|---|
| false | false | Omitted |
| false | true | Included |
| true | false | Included |
| true | true | Included |
This could reuse the existing configuration:
[features]
item_ids = false
but give it the narrower post-#34645 meaning of controlling outbound serialization only.
If reusing a removed feature name is undesirable, the same behavior could be exposed through a new, explicit option:
[features]
serialize_item_ids = false
or preferably as a provider-scoped option:
[model_providers.proxy]
serialize_item_ids = false
Conceptually, the outbound request preparation would retain internal IDs and clear IDs only on the request copy:
if !store && !serialize_item_ids {
for item in input {
item.set_id(None);
}
}
Alternative: explicit store override
Another option would be an explicit typed provider setting:
[model_providers.proxy]
responses_store = true
with behavior equivalent to:
store: provider
.responses_store
.unwrap_or_else(|| provider.is_azure_responses_endpoint())
This would preserve all current defaults while allowing an Azure endpoint hidden behind a local or corporate proxy to use the existing Azure behavior.
The key requirement is that custom providers have a supported way to select a valid request shape. Changing the provider display name to exactly azure should not be the only workaround.
Additional information
Affected surfaces
This issue was originally discovered in Codex Desktop while using a custom corporate Responses provider that forwards to Azure OpenAI.
The same request-shaping behavior was later reproduced independently with the public Codex CLI 0.146.0-alpha.3.1. The CLI reproduction isolates the problem to the shared codex-rs request construction behavior rather than the Desktop UI or Electron layer.
Relevant changes
- #34645 made response item IDs always assigned and retired
features.item_idsas a configurable feature. - #3528 introduced the existing Azure
store=trueworkaround. - #5458 is a related request for provider-specific request-body configuration.
- #31875 is an adjacent Azure/custom-provider compatibility report.
Current Azure documentation
Current Azure documentation supports both stored and stateless Responses usage. In stateless mode, it documents store=false together with reasoning.encrypted_content:
<https://learn.microsoft.com/en-us/azure/foundry/openai/how-to/responses#encrypted-reasoning-items>
The failing request in this report already contains non-empty encrypted_content. This issue does not assume that every Azure endpoint must use store=true; it requests an explicit custom-provider capability so Codex does not have to infer storage semantics from the visible proxy URL or display name.
Regression range
rust-v0.145.0does not contain #34645; default stateless requests omit outbound item IDs.rust-v0.146.0-alpha.1and later contain #34645; prefixed item IDs are always preserved in outbound requests.