BigPizzaV3/CodexPlusPlus · error

Chat Completions 协议暂不支持 Responses compact 请求

Error message

Chat Completions 协议暂不支持 Responses compact 请求

What it means

Thrown by upstream_request_parts in crates/codex-plus-core/src/protocol_proxy.rs when the incoming request path is a Responses compact endpoint (/responses/compact, /v1/responses/compact, /v1/v1/responses/compact, or /codex/v1/responses/compact per is_responses_compact_proxy_path) but the selected relay speaks the Chat Completions protocol. Compact (context-compaction) requests are forwarded verbatim in the Responses wire format; the responses_to_chat_completions converter does not implement a compact translation, so the combination is rejected explicitly.

Source

Thrown at crates/codex-plus-core/src/protocol_proxy.rs:920

        .to_string();

    Ok(UpstreamProxyResponse {
        status_code,
        is_stream: is_stream || content_type.contains("text/event-stream"),
        content_type,
        wire_api: UpstreamWireApi::ChatCompletions,
        response: upstream,
    })
}

async fn upstream_request_parts(
    relay: &crate::settings::RelayProfile,
    request_json: Value,
    request_path: &str,
) -> anyhow::Result<(String, Value, UpstreamWireApi)> {
    let compact = is_responses_compact_proxy_path(request_path);
    if compact && relay.protocol == RelayProtocol::ChatCompletions {
        anyhow::bail!("Chat Completions 协议暂不支持 Responses compact 请求");
    }
    let mut body = match relay.protocol {
        RelayProtocol::Responses => request_json,
        RelayProtocol::ChatCompletions => responses_to_chat_completions(request_json)?,
    };

    // Image handling (per-model): send-as-is / strip / VLM analysis
    let model = body
        .get("model")
        .and_then(Value::as_str)
        .unwrap_or("")
        .to_string();
    if !model.is_empty() {
        use crate::vision::ImageHandling;
        match crate::vision::image_handling_mode(&model, &relay.model_vlm) {
            ImageHandling::SendAsIs => { /* 不做任何处理 */ }
            ImageHandling::Strip => {
                for key in &["messages", "input"] {

View on GitHub (pinned to 1f431ae49b)

Solutions

  1. Switch the active provider (or the route target serving this model) to a relay using the Responses protocol
  2. Raise the auto-compact threshold / context window so compaction is deferred while on a Chat Completions relay
  3. Start a new conversation so no compaction is requested until you are back on a Responses-capable provider
Defensive patterns

Strategy: validation

Validate before calling

if crate::protocol_proxy::is_responses_compact_proxy_path(path)
    && relay.protocol == RelayProtocol::ChatCompletions
{
    anyhow::bail!("compact requires a Responses-protocol provider");
}

Type guard

fn relay_supports_compact(relay: &RelayProfile) -> bool {
    relay.protocol == RelayProtocol::Responses
}

Prevention

When it happens

Trigger: codex client triggers an automatic /v1/responses/compact call while the active relay profile protocol is ChatCompletions; a Chat Completions aggregate member is selected for a compact request during failover.

Common situations: Long codex sessions hitting the auto-compact threshold on a chat-completions-only relay; switching providers mid-conversation from Responses to Chat Completions and the next compaction fires; chat-completions vendors that never implemented the compact endpoint.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16). Data as JSON: /api/errors/73764ca04ffdfab2. Report an issue: GitHub.