router-for-me/CLIProxyAPI · error

create upstream WebRTC offer: %w

Error message

create upstream WebRTC offer: %w

What it means

Thrown when upstream.CreateOffer(nil) fails while generating the SDP offer to send to OpenAI. Pion CreateOffer errors when the connection state disallows offering (already closed/closing), when there are no media or data channels to describe, or on SDP marshaling failure. Here the DataChannel and audio track were just added, so state races dominate.

Source

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

			if errClose := channel.Close(); errClose != nil {
				log.WithError(errClose).Debug("codex live media: close unsupported downstream DataChannel")
			}
			return
		}
		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

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Retry the full session (new NewSession) when the client remains connected
  2. Audit for goroutines that call session.Close() during setup (bridge failure handler fires 'data_channel_failed')
  3. Align pion/webrtc version to pick up offer-generation fixes
Defensive patterns

Strategy: retry

Try / catch

offer, errOffer := upstream.CreateOffer(nil)
if errOffer != nil {
	if pcState := upstream.ConnectionState(); pcState == webrtc.PeerConnectionStateClosed {
		return nil, "", fmt.Errorf("session closed before offer: %w", errOffer)
	}
	// transient: retry once after brief backoff
	time.Sleep(50 * time.Millisecond)
	offer, errOffer = upstream.CreateOffer(nil)
}

Prevention

When it happens

Trigger: Upstream PC entered 'closed' state concurrently (session.Close raced setup), or internal SDP generation failure after adding the track/channel.

Common situations: Client disconnects mid-handshake causing teardown to race offer creation; rare pion internal errors.

Related errors


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