router-for-me/CLIProxyAPI · error
create downstream PeerConnection: %w
Error message
create downstream PeerConnection: %w
What it means
Thrown when r.downstreamAPI.NewPeerConnection(r.configuration) fails while creating the peer connection facing the local client. Pion returns errors for invalid ICE server URLs, bad STUN/TURN configuration, or an expired/closed API object. The limiter slot acquired just before is released via releaseSlot(). This is the first PeerConnection of the two the relay creates per session.
Source
Thrown at internal/client/codex/live/media.go:287
return nil, "", fmt.Errorf("configure Codex live remote TCP proxy: %w", errProxy)
}
proxied := proxyMode == proxyutil.ModeProxy
var proxyDialer proxy.ContextDialer
if proxied {
contextDialer, ok := builtProxyDialer.(proxy.ContextDialer)
if !ok {
return nil, "", errors.New("Codex live remote TCP proxy does not support cancellation")
}
proxyDialer = contextDialer
}
if !r.limiter.acquire() {
return nil, "", errors.New("Codex live media relay capacity exhausted")
}
releaseSlot := r.limiter.release
downstream, errDownstream := r.downstreamAPI.NewPeerConnection(r.configuration)
if errDownstream != nil {
releaseSlot()
return nil, "", fmt.Errorf("create downstream PeerConnection: %w", errDownstream)
}
upstreamAPI := r.upstreamAPI
upstreamConfiguration := r.configuration
if proxied {
upstreamAPI = r.proxyUpstreamAPI
upstreamConfiguration.ICEServers = nil
}
upstream, errUpstream := upstreamAPI.NewPeerConnection(upstreamConfiguration)
if errUpstream != nil {
releaseSlot()
if errClose := downstream.Close(); errClose != nil {
log.WithError(errClose).Debug("codex live media: close downstream PeerConnection after setup error")
}
return nil, "", fmt.Errorf("create upstream PeerConnection: %w", errUpstream)
}
session := &pionMediaSession{
downstream: downstream,View on GitHub (pinned to 78f0c4079e)
Solutions
- Validate every ICE server URL in codex-live-media-relay config (scheme stun/turn/turns, resolvable host, valid port)
- Retry the call once — ICE agent setup can fail transiently under fd/memory pressure
- Check host resource limits (ulimit -n) if failures cluster under load
- Verify credentials for TURN servers are current
Example fix
# before
codex-live-media-relay:
ice-servers:
- urls: ["turn turn.example.com"]
# after
codex-live-media-relay:
ice-servers:
- urls: ["turn:turn.example.com:3478?transport=udp"]
username: user
credential: pass Defensive patterns
Strategy: retry
Validate before calling
for _, server := range relayConfig.ICEServers {
for _, raw := range server.URLs {
u, err := url.Parse(strings.TrimSpace(raw))
if err != nil || (u.Scheme != "stun" && u.Scheme != "turn" && u.Scheme != "turns") {
return fmt.Errorf("invalid ICE server URL %q", raw)
}
}
} Try / catch
var downstream *webrtc.PeerConnection
var errDownstream error
for attempt := 0; attempt < 2; attempt++ {
downstream, errDownstream = api.NewPeerConnection(cfg)
if errDownstream == nil {
break
}
} Prevention
- Validate ICE server URLs at config load
- Monitor fd usage on the host running the relay
- Keep TURN credentials fresh and monitored
When it happens
Trigger: An ICE server entry in relayConfig.ICEServers with a malformed URL (wrong scheme, bad port), a TURN credential type mismatch, or resource exhaustion (socket/ICE agent creation failure) at session start.
Common situations: Bad stun:/turn: URL in the media relay config, TURN server password errors surfaced at PC creation, or transient fd exhaustion on a loaded host.
Related errors
- configure WebRTC UDP port range: %w
- create upstream PeerConnection: %w
- upstream WebRTC offer is empty
- downstream WebRTC answer is empty
- SDP contains incomplete ICE credentials
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/223acad254785457.
Report an issue: GitHub.