router-for-me/CLIProxyAPI · error
configure WebRTC UDP port range: %w
Error message
configure WebRTC UDP port range: %w
What it means
Thrown when SettingEngine.SetEphemeralUDPPortRange rejects the configured min/max port pair for the non-loopback Pion API. The pion API returns an error when min > max, when either port is outside 0-65535, or when the range includes privileged/invalid values. It comes from the codex-live-media-relay UDP port range config (UDPPortMin/UDPPortMax), only applied when not loopback-only and UDPPortMin != 0.
Source
Thrown at internal/client/codex/live/media.go:226
}
func newPionAPIWithOptions(relayConfig config.CodexLiveMediaRelayConfig, filterPrivateRemoteIPs, loopbackOnly bool) (*webrtc.API, error) {
mediaEngine := &webrtc.MediaEngine{}
if errRegister := mediaEngine.RegisterCodec(webrtc.RTPCodecParameters{
RTPCodecCapability: opusCodec,
PayloadType: 111,
}, webrtc.RTPCodecTypeAudio); errRegister != nil {
return nil, fmt.Errorf("register Opus codec: %w", errRegister)
}
interceptorRegistry := &interceptor.Registry{}
if errRegister := webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry); errRegister != nil {
return nil, fmt.Errorf("register WebRTC interceptors: %w", errRegister)
}
settingEngine := webrtc.SettingEngine{}
if !loopbackOnly {
if relayConfig.UDPPortMin != 0 {
if errPorts := settingEngine.SetEphemeralUDPPortRange(relayConfig.UDPPortMin, relayConfig.UDPPortMax); errPorts != nil {
return nil, fmt.Errorf("configure WebRTC UDP port range: %w", errPorts)
}
}
if publicIP := strings.TrimSpace(relayConfig.PublicIP); publicIP != "" {
settingEngine.SetNAT1To1IPs([]string{publicIP}, webrtc.ICECandidateTypeHost)
}
}
if filterPrivateRemoteIPs {
settingEngine.SetRemoteIPFilter(isPublicRemoteIP)
}
if loopbackOnly {
settingEngine.SetNetworkTypes([]webrtc.NetworkType{
webrtc.NetworkTypeUDP4,
webrtc.NetworkTypeUDP6,
webrtc.NetworkTypeTCP4,
webrtc.NetworkTypeTCP6,
})
settingEngine.SetIncludeLoopbackCandidate(true)
settingEngine.SetIPFilter(func(ip net.IP) bool {View on GitHub (pinned to 78f0c4079e)
Solutions
- Fix config so 0 < UDPPortMin <= UDPPortMax <= 65535 (e.g. min 50000, max 51000)
- Leave both unset (0) if you do not need a pinned UDP range — the code skips SetEphemeralUDPPortRange entirely
- Check config.CodexLiveMediaRelayConfig.Validate() if adding range validation so this fails at config load, not at relay construction
Example fix
# before (config.yaml) codex-live-media-relay: udp-port-min: 61000 udp-port-max: 50000 # after codex-live-media-relay: udp-port-min: 50000 udp-port-max: 61000
Defensive patterns
Strategy: validation
Validate before calling
if relayConfig.UDPPortMin != 0 {
if relayConfig.UDPPortMin < 1 || relayConfig.UDPPortMax < relayConfig.UDPPortMin || relayConfig.UDPPortMax > 65535 {
return fmt.Errorf("invalid UDP port range %d-%d", relayConfig.UDPPortMin, relayConfig.UDPPortMax)
}
} Prevention
- Always configure udp-port-min and udp-port-max as a pair
- Add the range check to config validation so it fails at config load
- Prefer leaving both unset unless firewall pinning requires them
When it happens
Trigger: Configuring relayConfig.UDPPortMin > relayConfig.UDPPortMax, setting a port above 65535 or negative, or setting only UDPPortMin while UDPPortMax stays 0 (min>max).
Common situations: YAML config typos in the media relay port range, swapping min and max keys, copying a range like 50000-40000, or setting UDPPortMin without UDPPortMax.
Related errors
- create downstream PeerConnection: %w
- upstream WebRTC offer is empty
- downstream WebRTC answer is empty
- register WebRTC interceptors: %w
- configure Codex live remote TCP proxy: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/c0c6201bb9f3d033.
Report an issue: GitHub.