가이드 목록으로
문제 해결·2026년 9월 23일·6분 분량

Codex “stream disconnected before completion” — 스트림을 종료한 원인과 Codex가 자체적으로 재시도하는 항목

Codex가 Responses 스트림을 읽고 있거나 열려고 했지만 response.completed 이벤트가 도착하기 전에 종료되었습니다. 연결이 닫혔거나, 무응답 상태가 되었거나, 네트워크 수준에서 끊겼거나, 서버가 실패를 보고했을 수 있습니다. Codex는 기본적으로 이를 자체적으로 5회 재시도합니다. 콜론 뒤에 출력되는 원인이 어떤 상황인지 알려 주며, 어디를 확인할지 결정합니다.

마지막 검토일: .

Codex가 Responses 스트림을 읽고 있거나 열려고 했지만 response.completed 이벤트가 도착하기 전에 종료되었습니다. 연결이 닫혔거나, 무응답 상태가 되었거나, 네트워크 수준에서 끊겼거나, 서버가 실패를 보고했을 수 있습니다. Codex는 기본적으로 이를 자체적으로 5회 재시도합니다. 콜론 뒤에 출력되는 원인이 어떤 상황인지 알려 주며, 어디를 확인할지 결정합니다.

오류

Codex output (layout varies by client)
# Codex CLI, once its retries are spent
■ stream disconnected before completion: stream closed before response.completed

# While it retries (VS Code extension, an early-2026 build)
Reconnecting... 1/5
stream disconnected before completion: error sending request for url (https://…/responses)

# The reason after the colon varies, and it is the diagnosis:
#   stream closed before response.completed
#   idle timeout waiting for SSE
#   error sending request            (Codex before 0.156 adds: for url (…))
#   An error occurred while processing your request. You can retry your request, …
#   Incomplete response returned, reason: max_output_tokens

원인과 해결 방법 한눈에 보기

원인해결 방법
VPN, 프록시, 방화벽 또는 TLS를 검사하는 중간 장치가 연결을 닫음다른 네트워크에서 재시도하세요. 오류가 중지되면 해당 프록시 또는 검사에서 API 호스트를 제외하세요.
서버가 응답 중간에 실패함 — 원인은 서버 자체 메시지로컬에서 변경할 사항은 없습니다. Codex가 재시도하도록 두고, 제공업체 상태를 확인한 다음 나중에 다시 시도하세요.
stream_idle_timeout_ms 동안 아무것도 도착하지 않음(기본값 300,000ms)중단된 업스트림 또는 버퍼링 프록시입니다. 정당한 무응답인 경우에만 시간 초과를 늘리세요.
response.completed 없이 스트림을 종료하는 사용자 지정 제공업체curl -N을 사용해 실행하세요. 성공한 모든 응답은 해당 이벤트로 끝나야 합니다.
응답이 의도적으로 종료됨 — "Incomplete response returned"토큰 상한, 콘텐츠 필터 또는 원인에 명시된 다른 중지 이유입니다. 재시도하면 대개 반복되므로 요청을 변경하세요.

콜론 뒤의 원인 읽기

Codex는 더 구체적인 진단 없이 조기에 종료되는 스트림에 이 오류 하나를 사용하고 원인을 덧붙입니다. 소스에서 단순히 종료되는 스트림은 "stream closed before response.completed"를 표시합니다. stream_idle_timeout_ms보다 오래 무응답 상태로 있으면 "idle timeout waiting for SSE"를 표시하며, 기본 제공 OpenAI 제공업체가 사용하는 WebSocket 전송에서는 "idle timeout waiting for websocket"을 표시합니다. 전송 중단이 발생한 요청은 HTTP 클라이언트의 표현인 "error sending request"를 유지하며, 0.156 이전 빌드에서는 URL도 추가됩니다. 일반적인 response.failed 이벤트는 콜론 뒤에 서버 메시지를 넣습니다. Codex 0.148부터 DNS, TLS, 거부된 포트 등 연결 자체를 열 수 없는 경우에는 별도 오류인 "Connection failed"로 보고되며, 현재 빌드는 네트워크를 기다리는 동안 이를 계속 재시도합니다.

what each reason means
stream closed before response.completed  the connection ended with no terminal event:
                                         network path, server, or a provider that
                                         never sends response.completed
idle timeout waiting for SSE             no event for stream_idle_timeout_ms
error sending request                    the request broke on the wire: a reset, a
                                         proxy or a middlebox (before 0.148, also
                                         a connection that never opened)
…error decoding response body            the body broke mid-read: network or middlebox
An error occurred while processing…      the server's own response.failed message
Incomplete response returned, reason: …  the server stopped it: a token cap, a content
                                         filter, or whatever the reason names

Codex가 이미 재시도하는 항목을 파악하고 제공업체별로 조정하기

두 가지 재시도 예산이 적용됩니다. request_max_retries(기본값 4)는 스트림이 존재하기 전의 HTTP 요청을 담당합니다. Codex는 여기서 5xx 응답과 전송 오류를 재시도하지만 429는 재시도하지 않습니다. stream_max_retries(기본값 5)는 이 페이지의 모든 항목을 담당합니다. 각 재시도는 차례를 다시 전송하며, "Reconnecting... 1/5"가 이를 세는 방식입니다. 예산이 소진되면 오류가 화면에 남고 차례가 중지됩니다. 두 값 모두 100으로 제한되며 [model_providers.<id>] 블록에 있습니다. 기본 제공 openai 제공업체 ID는 예약되어 재정의할 수 없으므로 이 설정은 사용자 지정 제공업체를 위한 조정값입니다.

~/.codex/config.toml
model = "gpt-5-6-sol"
model_provider = "kunavo"

[model_providers.kunavo]
name = "Kunavo"
base_url = "https://api.kunavo.com/v1"
env_key = "KUNAVO_API_KEY"
# wire_api defaults to "responses", the only supported value
stream_max_retries = 10          # dropped or failed streams (default 5, max 100)
request_max_retries = 4          # 5xx and network errors before streaming (default 4, max 100)
stream_idle_timeout_ms = 300000  # silence before giving up (default 300000)

Codex 없이 스트림 재현하기

Responses 스트림은 하나의 종료 이벤트로 끝나며, Codex는 이 이벤트가 response.completed이기를 필요로 합니다. 같은 컴퓨터에서 curl로 동일한 유형의 요청을 보내세요. 매번 완료되는데 Codex만 계속 연결이 끊긴다면 Codex 빌드와 공개 이슈를 확인하세요. curl도 실패한다면 제공업체를 탓하기 전에 다른 네트워크에서 반복하세요. 실패 시점을 기록하세요. 실행할 때마다 동일한 경과 시간에 끊긴다면 불안정한 네트워크가 아니라 경로 어딘가의 타이머를 가리킵니다.

reproduce.sh
curl -sN https://api.kunavo.com/v1/responses \
  -H "Authorization: Bearer $KUNAVO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-5-6-sol","stream":true,
       "input":"Write a 600-word story about a lighthouse keeper."}' \
  | grep -oE '"type": ?"response\.(completed|failed|incomplete)"'
# a healthy run prints exactly one line: "type":"response.completed"

네트워크 경로를 제외한 다음 제공업체를 확인하세요

무엇이든 결론 내리기 전에 두 번째 네트워크에서 테스트하세요. OpenAI 포럼에서는 한 사용자의 업무용 컴퓨터 오류가 회사의 Zscaler를 비활성화하는 순간 멈췄고, GPT-5.6 스레드에서는 한 사용자의 문제가 VPN이나 휴대폰 핫스팟에서 해결된 반면 다른 사용자의 문제는 네트워크를 바꾼 뒤에도 지속되었습니다. 다른 네트워크에서 해결된다면 타임아웃을 늘리지 말고 프록시 또는 TLS 검사에서 API 호스트를 제외하세요. 사용자 지정 제공업체의 경우 codex doctor는 구성이 로드되었는지와 제공업체의 키 변수가 있는지를 보고합니다. 제공업체는 Responses API를 제공해야 합니다. wire_api에는 다른 값이 없으며, Responses WebSocket 전송을 실행하는 경우가 아니면 supports_websockets는 설정하지 않은 상태로 두어야 합니다. curl이 정상적으로 완료되는데 Codex만 실패한다면 openai/codex 이슈 #41340 또는 #41989에 재현 내용을 추가하세요. 이 이슈들은 Codex 외부에서는 정상적으로 스트리밍되는 사용자 지정 Responses 제공업체에서 이 오류를 보고하며, 2026년 9월 23일에 아직 열려 있었습니다.

Kunavo를 통해 호출하는 경우

Kunavo를 통해 GPT 모델의 /v1/responses 스트림은 업스트림 자체의 이벤트 스트림을 프레임 단위로 중계한 것입니다. 변경되는 것은 모델 ID뿐이며 Kunavo는 keepalive 이벤트를 추가하지 않습니다. 첫 번째 출력 이벤트가 도착할 때까지 최대 30초 동안 스트림이 보류되므로, 이 단계에서 업스트림이 오류를 내거나 타임아웃되거나 연결을 끊어도 모델에 다음 채널이 구성되어 있다면 해당 채널에서 재시도할 수 있습니다. 이를 제공하는 채널이 없으면 Codex는 스트림 대신 HTTP 오류를 받습니다. 업스트림에서 오류가 발생했거나 응답하지 않았거나 Kunavo 자체의 키를 거부한 경우에는 502가 반환되며, 원인은 upstream_524 또는 upstream_403 같은 JSON code에 포함됩니다(다른 업스트림 4xx는 자체 상태를 유지합니다). 이 경우 Codex는 이를 이 메시지가 아니라 unexpected status 502 Bad Gateway: Upstream provider error로 출력하고 역시 재시도합니다. 첫 번째 출력 이벤트 이후에는 출력을 중복하지 않고는 아무것도 재시도할 수 없습니다. 업스트림의 response.failed는 전송된 그대로 전달되므로 Codex는 OpenAI에서 직접 받은 경우와 정확히 동일하게 처리합니다(일반 오류라면 콜론 뒤에 메시지를 출력합니다). 업스트림 연결이 응답 중간에 끊기면 Kunavo는 종료 이벤트 없이 스트림을 끝내며, Codex는 이를 stream closed before response.completed로 보고합니다. 어느 경우든 Codex 자체 재시도가 이어집니다. 계속 흐르는 스트림을 Kunavo 측에서 제한하는 것은 없습니다. 240초 제한은 업스트림 헤더를 기다리는 시간에만 적용됩니다. 다만 침묵은 스트림을 종료합니다. 300초 동안 아무것도 보내지 않는 업스트림은 Kunavo가 읽기를 중지하며, 이는 Codex의 기본 유휴 제한과 같습니다. 바이트를 전혀 전달하지 않는 연결은 엣지에서 600초 후 종료됩니다. 이러한 실패는 모두 비용 0으로 기록됩니다. 위에서 조정한 제공업체 블록은 다음에 설정되어 있습니다 Codex CLI 통합 페이지.

자주 묻는 질문

“stream closed before response.completed”는 무엇을 의미하나요?

HTTP 응답이 시작된 후 Codex가 기다리는 response.completed 이벤트 없이 연결이 종료되었다는 뜻입니다. 프록시나 방화벽, 서버 또는 해당 이벤트를 전혀 보내지 않는 사용자 지정 엔드포인트가 연결을 조기에 종료한 것입니다.

Codex는 “stream disconnected before completion”을 자동으로 재시도하나요?

예. Codex는 stream_max_retries 횟수만큼(기본값 5회, 최대 100회) 해당 턴을 다시 보내며, 그동안 Reconnecting... 1/5을 표시합니다. 재시도 예산이 소진되면 오류가 화면에 남고 턴이 중지됩니다. 다른 메시지를 보내면 새 요청이 시작됩니다.

stream_idle_timeout_ms를 늘려야 하나요?

이유가 "idle timeout waiting for SSE"이고 침묵이 정상적인 경우에만 늘리세요. 연결이 조용해진 것이 아니라 종료된 "stream closed before response.completed"에는 아무 효과가 없습니다. Kunavo를 통해 스트림이 시작된 뒤에는 300000보다 큰 값도 아무런 이득이 없습니다. Kunavo는 300초 동안 아무것도 보내지 않는 업스트림 읽기를 중지하고 스트림을 종료합니다.

Codex가 “Incomplete response returned, reason: max_output_tokens”라고 말하는 이유는 무엇인가요?

서버가 토큰 한도에서 응답을 중지하고 response.incomplete 이벤트로 그 사실을 알렸습니다. Codex는 동일한 오류로 이를 보고하고 재시도하지만, 동일한 턴을 재시도하면 보통 같은 한도에 다시 도달합니다. 따라서 작업을 나누거나 출력 한도가 더 큰 모델을 사용하세요. Kunavo를 통해 Claude 모델의 max-token 중지도 같은 방식으로 Codex에 도달합니다.

재시도에도 요금이 청구되나요?

각 재시도는 새 요청입니다. Kunavo를 통해 업스트림에서 실패한 GPT 호출(스트리밍 전 오류, response.failed, 연결 끊김)은 비용 0으로 기록됩니다. Codex가 포기했지만 업스트림은 계속 작업한 시도에는 업스트림이 생성했다고 보고한 만큼 요금이 청구됩니다. 해당 작업이 실제로 수행되었기 때문입니다.

관련 가이드

오류 의미에 대한 자세한 내용은 오류 참조에서 확인할 수 있습니다. 가입 및 인증 가이드를 통해 1분이면 키를 받을 수 있습니다.