Bug Report: `/compact` Command Fails in Chat Completions API Mode

Resolved 💬 3 comments Opened Aug 18, 2025 by astrosheep-zero Closed Aug 25, 2025
💡 Likely answer: A maintainer (seratch, member) responded on this thread — see the highlighted reply below.

What version of Codex is running?

codex-cli 0.22.0

Which model were you using?

gpt-5

What platform is your computer?

_No response_

What steps can reproduce the bug?

  1. Configure a provider with wire_api: chat
  2. Start a conversation with any prompt
  3. Trigger the /compact command
  4. Result: Error message "🖐 stream disconnected before completion: token_usage was None in ResponseEvent::Completed"

What is the expected behavior?

_No response_

What do you see instead?

The /compact command (summarization feature) fails when using the Chat Completions API mode, causing the stream to disconnect and the session to become unresponsive.

Additional information

Possible reason:

  1. Chat parser never populates token usage:

```rust src/chat_completions.rs
// In the Chat SSE parser, Completed events are created with token_usage: None
ResponseEvent::Completed {
response_id: String::new(),
token_usage: None
}


2. **Compact flow requires token usage:**
```rust src/codex.rs
// In drain_to_completed, None token_usage causes an error
match event {
    ResponseEvent::Completed { token_usage } => {
        if let Some(token_usage) = token_usage {
            // Success path...
        } else {
            return Err(CodexErr::Stream(
                "token_usage was None in ResponseEvent::Completed",
                None,
            ));
        }
    }
    // ...
}

View original on GitHub ↗

3 Comments

seratch member · 1 year ago

I tried to reproduce this but I couldn't with the following basic one:

model = "gpt-5"
model_provider = "openai-chat-completions"

[model_providers.openai-chat-completions]
# Name of the provider that will be displayed in the Codex UI.
name = "OpenAI using Chat Completions"
# The path `/chat/completions` will be amended to this URL to make the POST
# request for the chat completions.
base_url = "https://api.openai.com/v1"
# If `env_key` is set, identifies an environment variable that must be set when
# using Codex with this provider. The value of the environment variable must be
# non-empty and will be used in the `Bearer TOKEN` HTTP header for the POST request.
env_key = "OPENAI_API_KEY"
# Valid values for wire_api are "chat" and "responses". Defaults to "chat" if omitted.
wire_api = "chat"
# If necessary, extra query params that need to be added to the URL.
# See the Azure example below.
query_params = {}

Does this still always happen to you? Do you have repro steps so we can clearly see the situation?

astrosheep-zero · 1 year ago
I tried to reproduce this but I couldn't with the following basic one: `` model = "gpt-5" model_provider = "openai-chat-completions" [model_providers.openai-chat-completions] # Name of the provider that will be displayed in the Codex UI. name = "OpenAI using Chat Completions" # The path /chat/completions will be amended to this URL to make the POST # request for the chat completions. base_url = "https://api.openai.com/v1" # If env_key is set, identifies an environment variable that must be set when # using Codex with this provider. The value of the environment variable must be # non-empty and will be used in the Bearer TOKEN HTTP header for the POST request. env_key = "OPENAI_API_KEY" # Valid values for wire_api are "chat" and "responses". Defaults to "chat" if omitted. wire_api = "chat" # If necessary, extra query params that need to be added to the URL. # See the Azure example below. query_params = {} `` Does this still always happen to you? Do you have repro steps so we can clearly see the situation?

Thanks for your reply!

I've reproduced this issue consistently with my third-party provider. I'll test with OpenRouter or the official API to check if it's related to SSE chunk differences and share what I find.

In the meantime, I notice that in source code, for chat completion path, it never reads or forward the usage field from upstream. As I originally posted, the issue is likely relative to this.

https://github.com/openai/codex/blob/202af129262ca6897d1ff051eb6d6b1c266072b5/codex-rs/core/src/chat_completions.rs#L226

// Stream closed gracefully – emit Completed with dummy id.
let _ = tx_event
    .send(Ok(ResponseEvent::Completed {
        response_id: String::new(),
        token_usage: None,
    }))
    .await;
oyiakoumis contributor · 1 year ago

I was able to reproduce this issue with OpenRouter using the following config:

[model_providers.openrouter-chat-completions]
name = "OpenRouter"
base_url = "https://openrouter.ai/api/v1"
env_key = "OPENROUTER_API_KEY"
wire_api = "chat"
query_params = {}

With OpenRouter and gpt-5, I sent a prompt to Codex and the response did not include any token counts, but no error was raised.
However, when using /compact, the code raised an error if token_usage was None.

I opened a PR to align the behavior in both cases: https://github.com/openai/codex/pull/2640.

It may also be worth investigating why OpenRouter does not return any token counts at all — that could require a separate fix.