Skip to content

[Bug] Valid Responses API compaction streams are rejected as empty_stream #1398

Description

@mizuikki

Summary

On CCH 0.9.1, a valid Responses API compaction stream can be rejected by the stream content gate as stream_gate_precommit with reason empty_stream.

The upstream response is not empty. It contains a completed compaction output item with non-empty encrypted content, followed by a successful response.completed event. However, the Responses stream classifier does not currently treat that encrypted compaction content as a content frame.

Environment

  • CCH Docker image: 0.9.1
  • Endpoint: /v1/responses
  • Client: Codex-style Responses API client
  • Request: streaming request with a compaction_trigger

Observed behavior

The gate reports an error similar to:

{
  "type": "stream_gate_precommit",
  "reason": "empty_stream",
  "family": "responses-api",
  "frames_seen": 9,
  "buffered_bytes": 199418,
  "echo_excluded_bytes": 99068
}

The terminal frame is response.completed with status: "completed" and error: null. The response also includes a response.output_item.done item with type: "compaction" and non-empty encrypted_content.

The request is then treated as a failed upstream attempt and can ultimately be returned as a 503 after fallback attempts.

Expected behavior

A non-empty Responses API compaction item should count as valid stream content and be forwarded to the client. A successful response.completed event containing a compaction result should not be classified as an empty stream.

Reproduction

  1. Run CCH 0.9.1 with the stream content gate enabled and request replay enabled.
  2. Send a streaming /v1/responses request from a Codex-style client with compaction_trigger.
  3. Use a context large enough for the upstream to return a compaction item.
  4. Observe stream_gate_precommit / empty_stream, even though the upstream response contains encrypted compaction content.

Related configuration issue

Setting stream_gate_mode=off does not fully disable this gate when request replay is enabled. The forwarding path still runs the precommit gate for replay owner sessions:

gateMode === "enforce" || session.replayState?.role === "owner"

This makes off misleading for those requests. Explicitly setting replay to false allows the same compaction request to complete successfully.

Suggested fixes

  • Recognize non-empty item.encrypted_content for Responses API compaction output items as valid content.
  • Consider making stream_gate_mode=off an unconditional bypass, or document clearly that replay owner sessions override this setting.
  • Add regression tests covering streamed compaction output followed by response.completed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions