MHSanaei/3x-ui · error

unsupported proxy scheme %q

Error message

unsupported proxy scheme %q

What it means

After a socks5/socks5h and http/https case, NewHTTPClient's switch rejects every other scheme with 'unsupported proxy scheme %q'. The accepted set is exactly socks5, socks5h, http, https (matched case-insensitively). This is a strict allowlist: socks4, socks4a, ssh, or scheme-relative '//host:port' all land here.

Source

Thrown at internal/util/netproxy/netproxy.go:61

		if parsed.User != nil {
			password, _ := parsed.User.Password()
			auth = &proxy.Auth{User: parsed.User.Username(), Password: password}
		}
		dialer, err := proxy.SOCKS5("tcp", parsed.Host, auth, proxy.Direct)
		if err != nil {
			return nil, fmt.Errorf("create socks5 dialer: %w", err)
		}
		if contextDialer, ok := dialer.(proxy.ContextDialer); ok {
			transport.DialContext = contextDialer.DialContext
		} else {
			transport.DialContext = func(_ context.Context, network, addr string) (net.Conn, error) {
				return dialer.Dial(network, addr)
			}
		}
	case "http", "https":
		transport.Proxy = http.ProxyURL(parsed)
	default:
		return nil, fmt.Errorf("unsupported proxy scheme %q", parsed.Scheme)
	}

	return &http.Client{Timeout: timeout, Transport: transport}, nil
}

func baseTransport() *http.Transport {
	if base, ok := http.DefaultTransport.(*http.Transport); ok {
		return base.Clone()
	}
	return &http.Transport{}
}

View on GitHub (pinned to ad32144c42)

Solutions

  1. Change the scheme to one of socks5, socks5h, http, or https.
  2. If the scheme was omitted, prepend socks5:// (or http://) explicitly.
  3. For SOCKS4 proxies, put a SOCKS5 front (e.g. gost) in front or switch the proxy software to SOCKS5 mode.

Example fix

// before
proxyURL := "127.0.0.1:1080" // no scheme -> unsupported proxy scheme ""

// after
proxyURL := "socks5://127.0.0.1:1080"
Defensive patterns

Strategy: validation

Validate before calling

var allowedSchemes = map[string]bool{"socks5": true, "socks5h": true, "http": true, "https": true}

func allowedProxyScheme(raw string) bool {
	u, err := url.Parse(strings.TrimSpace(raw))
	if err != nil { return false }
	return u.Scheme != "" && allowedSchemes[strings.ToLower(u.Scheme)]
}

Type guard

func allowedProxyScheme(raw string) bool {
	u, err := url.Parse(strings.TrimSpace(raw))
	if err != nil { return false }
	return allowedSchemes[strings.ToLower(u.Scheme)]
}

Prevention

When it happens

Trigger: Setting the proxy URL to socks4://..., ssh://..., or a value like '127.0.0.1:1080' with no scheme (url.Parse yields Scheme=""), then calling NewHTTPClient.

Common situations: User pastes a SOCKS4 proxy from an old config; omits the scheme entirely assuming SOCKS default; typo 'socks5h :' with a space; uses 'https_proxy' style env values with unsupported schemes.

Related errors


AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15). Data as JSON: /api/errors/a604ba1c3efdb906. Report an issue: GitHub.