router-for-me/CLIProxyAPI · error
wsrelay: connection closed during response
Error message
wsrelay: connection closed during response
What it means
In internal/wsrelay/http.go the client relays an HTTP request over a websocket session and waits on respCh for the upstream answer. In non-stream mode, if the channel closes before any MessageTypeHTTPResp or MessageTypeError arrives (streamMode is false), it returns `wsrelay: connection closed during response`. This means the relay websocket terminated mid-flight — the peer went away, the session hit a deadline, or the relay session was dropped — so no response body will ever arrive.
Source
Thrown at internal/wsrelay/http.go:68
streamResp *HTTPResponse
streamBody bytes.Buffer
)
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
case msg, ok := <-respCh:
if !ok {
if streamMode {
if streamResp == nil {
streamResp = &HTTPResponse{Status: http.StatusOK, Headers: make(http.Header)}
} else if streamResp.Headers == nil {
streamResp.Headers = make(http.Header)
}
streamResp.Body = append(streamResp.Body[:0], streamBody.Bytes()...)
return streamResp, nil
}
return nil, errors.New("wsrelay: connection closed during response")
}
switch msg.Type {
case MessageTypeHTTPResp:
resp := decodeResponse(msg.Payload)
if streamMode && streamBody.Len() > 0 && len(resp.Body) == 0 {
resp.Body = append(resp.Body[:0], streamBody.Bytes()...)
}
return resp, nil
case MessageTypeError:
return nil, decodeError(msg.Payload)
case MessageTypeStreamStart, MessageTypeStreamChunk:
if msg.Type == MessageTypeStreamStart {
streamMode = true
streamResp = decodeResponse(msg.Payload)
if streamResp.Headers == nil {
streamResp.Headers = make(http.Header)
}
streamBody.Reset()View on GitHub (pinned to 78f0c4079e)
Solutions
- Retry the request: channel-closed is transient; a new relay session re-establishes the websocket.
- Check wsrelay session deadline configuration in internal/wsrelay/session.go and raise it if non-streaming responses regularly outlast it.
- Verify the relay peer process is alive and not OOM-killed/restarting (inspect logs around the failure time).
- Enable websocket keepalive/ping on the relay path so intermediaries do not reap the connection.
- Switch the call to streaming mode, which returns the buffered partial body instead of this hard error.
Defensive patterns
Strategy: retry
Type guard
func isRelayClosedDuringResponse(err error) bool {
return err != nil && strings.Contains(err.Error(), "wsrelay: connection closed during response")
} Try / catch
resp, err := relayClient.Do(ctx, req)
if isRelayClosedDuringResponse(err) {
// idempotent retry with a fresh relay session; back off once first
time.Sleep(500 * time.Millisecond)
resp, err = relayClient.Do(ctx, req)
} Prevention
- Size wsrelay session deadlines above your longest non-streaming generation.
- Prefer streaming mode for long requests — it returns buffered partial data instead of failing hard.
- Monitor relay peer liveness and restart it before sessions expire.
When it happens
Trigger: Non-streaming HTTP request relayed through internal/wsrelay where the relay websocket closes after the request is sent but before the MessageTypeHTTPResp frame arrives: upstream process crash/restart, wsrelay session deadline expiry (internal/wsrelay/session.go deadlines), network interruption between proxy and relay peer, or peer calling Close() during the round trip.
Common situations: Codex websocket relay deployments where the remote relay process restarts under load; long non-streaming generations outlasting the relay session lifetime; proxies/LB killing idle-looking websocket connections; flaky networks between the proxy host and the relay host.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- wsrelay: stream closed
- Codex live request body too large
- Codex live session field must contain valid JSON
- previous_response_not_found
- wsrelay: unknown error
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/429294ccbd2a4fb6.
Report an issue: GitHub.