{"record":{"id":"5672f4d455dadd7f","repo":"router-for-me/CLIProxyAPI","slug":"register-webrtc-interceptors-w","errorCode":null,"errorMessage":"register WebRTC interceptors: %w","messagePattern":"register WebRTC interceptors: %w","errorType":"http","errorClass":null,"httpStatus":503,"severity":"critical","filePath":"internal/client/codex/live/media.go","lineNumber":220,"sourceCode":"func newPionAPI(relayConfig config.CodexLiveMediaRelayConfig, filterPrivateRemoteIPs bool) (*webrtc.API, error) {\n\treturn newPionAPIWithOptions(relayConfig, filterPrivateRemoteIPs, false)\n}\n\nfunc newPionProxyAPI(relayConfig config.CodexLiveMediaRelayConfig) (*webrtc.API, error) {\n\treturn newPionAPIWithOptions(relayConfig, false, true)\n}\n\nfunc newPionAPIWithOptions(relayConfig config.CodexLiveMediaRelayConfig, filterPrivateRemoteIPs, loopbackOnly bool) (*webrtc.API, error) {\n\tmediaEngine := &webrtc.MediaEngine{}\n\tif errRegister := mediaEngine.RegisterCodec(webrtc.RTPCodecParameters{\n\t\tRTPCodecCapability: opusCodec,\n\t\tPayloadType:        111,\n\t}, webrtc.RTPCodecTypeAudio); errRegister != nil {\n\t\treturn nil, fmt.Errorf(\"register Opus codec: %w\", errRegister)\n\t}\n\tinterceptorRegistry := &interceptor.Registry{}\n\tif errRegister := webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry); errRegister != nil {\n\t\treturn nil, fmt.Errorf(\"register WebRTC interceptors: %w\", errRegister)\n\t}\n\tsettingEngine := webrtc.SettingEngine{}\n\tif !loopbackOnly {\n\t\tif relayConfig.UDPPortMin != 0 {\n\t\t\tif errPorts := settingEngine.SetEphemeralUDPPortRange(relayConfig.UDPPortMin, relayConfig.UDPPortMax); errPorts != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"configure WebRTC UDP port range: %w\", errPorts)\n\t\t\t}\n\t\t}\n\t\tif publicIP := strings.TrimSpace(relayConfig.PublicIP); publicIP != \"\" {\n\t\t\tsettingEngine.SetNAT1To1IPs([]string{publicIP}, webrtc.ICECandidateTypeHost)\n\t\t}\n\t}\n\tif filterPrivateRemoteIPs {\n\t\tsettingEngine.SetRemoteIPFilter(isPublicRemoteIP)\n\t}\n\tif loopbackOnly {\n\t\tsettingEngine.SetNetworkTypes([]webrtc.NetworkType{\n\t\t\twebrtc.NetworkTypeUDP4,","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/client/codex/live/media.go#L202-L238","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ninterceptorRegistry := &interceptor.Registry{}\nif errRegister := webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry); errRegister != nil {\n\treturn nil, fmt.Errorf(\"register WebRTC interceptors: %w\", errRegister)\n}\n\n// after (diagnostic isolation)\ninterceptorRegistry := &interceptor.Registry{}\nif errRegister := webrtc.RegisterDefaultInterceptors(mediaEngine, interceptorRegistry); errRegister != nil {\n\treturn nil, fmt.Errorf(\"register WebRTC interceptors: %w (webrtc=%s interceptor=%s)\", errRegister, webrtc.Version, interceptor.Version)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if relay, err := newPionMediaRelay(relayConfig); err != nil {\n\tif strings.Contains(err.Error(), \"register WebRTC interceptors\") {\n\t\tlog.WithError(err).Error(\"pion interceptor/media-engine version mismatch; align pion modules\")\n\t}\n\treturn relay, err\n}","preventionTips":["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"],"tags":["webrtc","pion","initialization","dependency-mismatch"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}