router-for-me/CLIProxyAPI · error

codex.live-media-relay.ice-servers[%d] uses unsupported sche

Error message

codex.live-media-relay.ice-servers[%d] uses unsupported scheme %q

What it means

Only the STUN/TURN scheme family is supported for ICE servers: stun, stuns, turn, turns (case-insensitive). Any other scheme — http, https, or a misspelling — fails validation with the offending scheme echoed in the message.

Source

Thrown at internal/config/codex_live.go:101

		availablePorts := int(c.UDPPortMax) - int(c.UDPPortMin) + 1
		requiredPorts := c.EffectiveMaxSessions() * 2
		if availablePorts < requiredPorts {
			return fmt.Errorf("codex.live-media-relay UDP range requires at least %d ports for %d sessions", requiredPorts, c.EffectiveMaxSessions())
		}
	}
	for serverIndex, server := range c.ICEServers {
		if len(server.URLs) == 0 {
			return fmt.Errorf("codex.live-media-relay.ice-servers[%d].urls is required", serverIndex)
		}
		for _, rawURL := range server.URLs {
			parsed, errParse := url.Parse(strings.TrimSpace(rawURL))
			if errParse != nil || parsed.Scheme == "" {
				return fmt.Errorf("codex.live-media-relay.ice-servers[%d] contains an invalid URL", serverIndex)
			}
			switch strings.ToLower(parsed.Scheme) {
			case "stun", "stuns", "turn", "turns":
			default:
				return fmt.Errorf("codex.live-media-relay.ice-servers[%d] uses unsupported scheme %q", serverIndex, parsed.Scheme)
			}
		}
	}
	return nil
}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Change the scheme to stun/stuns/turn/turns as appropriate: 'stun:host:19302' or 'turns:host:5349'.
  2. For TURN over TLS use turns:, for STUN over TLS use stuns: — not https:.
  3. Re-run config load after the fix; the message shows exactly which scheme was rejected.

Example fix

# before
urls:
  - https://stun.example.com:19302

# after
urls:
  - stuns:stun.example.com:19302
Defensive patterns

Strategy: validation

Validate before calling

allowed := map[string]bool{"stun": true, "stuns": true, "turn": true, "turns": true}
for _, u := range server.URLs {
	p, _ := url.Parse(strings.TrimSpace(u))
	if !allowed[strings.ToLower(p.Scheme)] {
		return fmt.Errorf("unsupported scheme %q", p.Scheme)
	}
}

Type guard

func isSupportedICEScheme(raw string) bool {
	p, err := url.Parse(strings.TrimSpace(raw))
	if err != nil { return false }
	switch strings.ToLower(p.Scheme) {
	case "stun", "stuns", "turn", "turns":
		return true
	}
	return false
}

Prevention

When it happens

Trigger: Validate's switch on strings.ToLower(parsed.Scheme) hits default — e.g. 'https://stun.example.com' used because it looked like a normal web endpoint, or 'stun:' fat-fingered as 'stunN:'.

Common situations: Users wrap the STUN host in https:// out of habit; tooling templates prepend https://; typo'd scheme after editing.

Related errors


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