router-for-me/CLIProxyAPI · critical
register WebRTC interceptors: %w
Error message
register WebRTC interceptors: %w
What it means
Thrown when pion/webrtc v4's RegisterDefaultInterceptors fails while building the MediaEngine/interceptor stack for the Codex live media relay. RegisterDefaultInterceptors installs NACK/TWCC/RTCP-report interceptors and returns an error if the MediaEngine has no codecs registered or an internal interceptor factory rejects the configuration. In this code the Opus codec was registered just above, so failure almost always indicates a MediaEngine/interceptor version mismatch or an empty codec list.
Source
Thrown at internal/client/codex/live/media.go:220
func newPionAPI(relayConfig config.CodexLiveMediaRelayConfig, filterPrivateRemoteIPs bool) (*webrtc.API, error) {
return newPionAPIWithOptions(relayConfig, filterPrivateRemoteIPs, false)
}
func newPionProxyAPI(relayConfig config.CodexLiveMediaRelayConfig) (*webrtc.API, error) {
return newPionAPIWithOptions(relayConfig, false, true)
}
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,View on GitHub (pinned to 78f0c4079e)
Solutions
- Run 'go mod tidy' and align github.com/pion/interceptor with the version required by the github.com/pion/webrtc/v4 release in go.mod
- Verify the mediaEngine.RegisterCodec(opus ...) call above line 220 still executes successfully (error 320 cannot be reached if that already failed)
- Check 'go list -m github.com/pion/webrtc/v4 github.com/pion/interceptor' for unexpected module replacements
- If persisting, rebuild the relay with a minimal interceptor set (Registry.Add of only NACK) to isolate the failing factory
Example fix
// before
interceptorRegistry := &interceptor.Registry{}
if errRegister := webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry); errRegister != nil {
return nil, fmt.Errorf("register WebRTC interceptors: %w", errRegister)
}
// after (diagnostic isolation)
interceptorRegistry := &interceptor.Registry{}
if errRegister := webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry); errRegister != nil {
return nil, fmt.Errorf("register WebRTC interceptors: %w (webrtc=%s interceptor=%s)", errRegister, webrtc.Version, interceptor.Version)
} Defensive patterns
Strategy: try-catch
Try / catch
if relay, err := newPionMediaRelay(relayConfig); err != nil {
if strings.Contains(err.Error(), "register WebRTC interceptors") {
log.WithError(err).Error("pion interceptor/media-engine version mismatch; align pion modules")
}
return relay, err
} Prevention
- Keep github.com/pion/webrtc/v4 and github.com/pion/interceptor versions locked together in go.mod
- Run 'go mod tidy' in CI to catch transitive downgrades
- Fail relay construction loudly at startup rather than lazily at first session
When it happens
Trigger: Calling newPionAPIWithOptions (via newPionMediaRelay at relay construction, i.e. process/config load time) with a pion/webrtc or pion/interceptor version pair whose APIs are incompatible, or a code path that removed the preceding mediaEngine.RegisterCodec call leaving zero codecs.
Common situations: Upgrading pion/webrtc v4 without upgrading pion/interceptor in lockstep (go.mod replaces or transitive downgrades), vendored mixed versions, or a refactor that drops the Opus registration before RegisterDefaultInterceptors.
Related errors
- upstream WebRTC offer is empty
- downstream WebRTC answer is empty
- configure WebRTC UDP port range: %w
- create downstream PeerConnection: %w
- create upstream PeerConnection: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/5672f4d455dadd7f.
Report an issue: GitHub.