router-for-me/CLIProxyAPI · error

set upstream WebRTC offer: %w

Error message

set upstream WebRTC offer: %w

What it means

Thrown when upstream.SetLocalDescription(offer) fails while committing the locally generated offer. After SetLocalDescription, ICE candidate gathering begins (the gatherComplete promise below). Pion fails this when the description state is inconsistent (offer already set, PC closing) or the SDP cannot be re-parsed — typically a state race with session teardown.

Source

Thrown at internal/client/codex/live/media.go:389

		}
		session.bridge.attachDownstream(channel)
	})
	upstreamChannel, errChannel := upstream.CreateDataChannel(realtimeDataChannelLabel, nil)
	if errChannel != nil {
		_ = session.Close()
		return nil, "", fmt.Errorf("create upstream DataChannel: %w", errChannel)
	}
	session.bridge.attachUpstream(upstreamChannel)

	gatherComplete := webrtc.GatheringCompletePromise(upstream)
	offer, errOffer := upstream.CreateOffer(nil)
	if errOffer != nil {
		_ = session.Close()
		return nil, "", fmt.Errorf("create upstream WebRTC offer: %w", errOffer)
	}
	if errLocal := upstream.SetLocalDescription(offer); errLocal != nil {
		_ = session.Close()
		return nil, "", fmt.Errorf("set upstream WebRTC offer: %w", errLocal)
	}
	select {
	case <-gatherComplete:
	case <-ctx.Done():
		_ = session.Close()
		return nil, "", fmt.Errorf("gather upstream WebRTC candidates: %w", ctx.Err())
	}
	localDescription := upstream.LocalDescription()
	if localDescription == nil || strings.TrimSpace(localDescription.SDP) == "" {
		_ = session.Close()
		return nil, "", errors.New("upstream WebRTC offer is empty")
	}
	session.localOffer = localDescription.SDP
	return session, localDescription.SDP, nil
}

func (s *pionMediaSession) AcceptUpstreamAnswer(ctx context.Context, upstreamAnswer string) (string, error) {
	if s == nil || s.upstream == nil || s.downstream == nil {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Retry session establishment if the client is still connected
  2. Ensure handshake timeouts do not close the session before SetLocalDescription completes
  3. Keep pion/webrtc current for ICE-agent state race fixes
Defensive patterns

Strategy: retry

Try / catch

if errLocal := upstream.SetLocalDescription(offer); errLocal != nil {
	if upstream.ConnectionState() == webrtc.PeerConnectionStateClosed {
		return nil, "", fmt.Errorf("upstream closed during offer commit: %w", errLocal)
	}
	return nil, "", errLocal
}

Prevention

When it happens

Trigger: Concurrent Close() during setup, double SetLocalDescription, or ICE agent shutdown initiated between CreateOffer and SetLocalDescription.

Common situations: Handshake-timeout handlers firing too aggressively and tearing down the session mid-offer; client cancellation racing setup.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/9623bc5557f77b9e. Report an issue: GitHub.