{"record":{"id":"b4beda8357df8470","repo":"router-for-me/CLIProxyAPI","slug":"set-upstream-webrtc-answer-w","errorCode":null,"errorMessage":"set upstream WebRTC answer: %w","messagePattern":"set upstream WebRTC answer: %w","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"internal/client/codex/live/media.go","lineNumber":432,"sourceCode":"\t\t\treturn \"\", errProxy\n\t\t}\n\t\tfor _, tunnel := range tunnels {\n\t\t\ttunnel.setForwardingStartedHandler(s.logForwardingStarted)\n\t\t}\n\t\tif !s.installCandidateTunnels(tunnels) {\n\t\t\terrClosed := errors.New(\"Codex live media session closed while configuring TCP proxy\")\n\t\t\tif errClose := closeCandidateTunnels(tunnels); errClose != nil {\n\t\t\t\treturn \"\", errors.Join(errClosed, fmt.Errorf(\"close TCP candidate tunnels: %w\", errClose))\n\t\t\t}\n\t\t\treturn \"\", errClosed\n\t\t}\n\t\tanswerToApply = rewrittenAnswer\n\t}\n\tif errRemote := s.upstream.SetRemoteDescription(webrtc.SessionDescription{\n\t\tType: webrtc.SDPTypeAnswer,\n\t\tSDP:  answerToApply,\n\t}); errRemote != nil {\n\t\terrSetRemote := fmt.Errorf(\"set upstream WebRTC answer: %w\", errRemote)\n\t\tif errClose := s.closeCandidateTunnels(); errClose != nil {\n\t\t\treturn \"\", errors.Join(errSetRemote, fmt.Errorf(\"close TCP candidate tunnels: %w\", errClose))\n\t\t}\n\t\treturn \"\", errSetRemote\n\t}\n\tgatherComplete := webrtc.GatheringCompletePromise(s.downstream)\n\tanswer, errAnswer := s.downstream.CreateAnswer(nil)\n\tif errAnswer != nil {\n\t\treturn \"\", fmt.Errorf(\"create downstream WebRTC answer: %w\", errAnswer)\n\t}\n\tif errLocal := s.downstream.SetLocalDescription(answer); errLocal != nil {\n\t\treturn \"\", fmt.Errorf(\"set downstream WebRTC answer: %w\", errLocal)\n\t}\n\tselect {\n\tcase <-gatherComplete:\n\tcase <-ctx.Done():\n\t\treturn \"\", fmt.Errorf(\"gather downstream WebRTC candidates: %w\", ctx.Err())\n\t}","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/client/codex/live/media.go#L414-L450","documentation":"Thrown when upstream.SetRemoteDescription fails applying OpenAI's answer SDP on the upstream PeerConnection. Pion rejects answers whose SDP does not match the previously set local offer (different media sections, ICE ufrag/pwd mismatch, missing attributes), malformed SDP, or an invalid state for an answer. On the proxied path the answer was rewritten by prepareProxiedUpstreamAnswer first — a bad rewrite produces the same failure.","triggerScenarios":"The answer SDP from upstream is corrupted by the TCP-proxy candidate rewriting, the answer does not correspond to localOffer, or the upstream PC is already closed when the answer arrives.","commonSituations":"Proxy-mode candidate rewriting bugs (version-sensitive), a late answer arriving after session teardown/retry, or upstream protocol changes in the Codex live handshake.","solutions":["If not using a proxy route, verify the raw upstream answer is passed unmodified","If proxied, check that the proxy is a plain CONNECT-style forwarder that does not mangle payloads","Discard late answers: do not call AcceptUpstreamAnswer after Close or after a retry started a new session","Compare localOffer m-lines with the answer's to spot mismatch (audio + application sections expected)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"func isLikelyAnswerMismatch(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"set upstream WebRTC answer\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := session.AcceptUpstreamAnswer(ctx, answer); err != nil {\n\tvar stateErr *webrtc.InvalidStateError\n\tswitch {\n\tcase errors.As(err, &stateErr):\n\t\tlog.WithError(err).Warn(\"answer applied to closed/dirty upstream PC; discard session\")\n\tdefault:\n\t\tlog.WithError(err).Error(\"upstream answer rejected; check SDP/proxy rewriting\")\n\t}\n}","preventionTips":["Deliver the upstream answer exactly once and only to the session that issued the offer","Discard answers arriving after retries started a new session","On proxied routes, verify the proxy does not alter SDP payloads"],"tags":["webrtc","sdp","answer","negotiation","upstream"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}