fish2018/pansou · error

SOCKS5代理初始化失败

Error message

SOCKS5代理初始化失败: %w

What it means

For schemes 'socks5'/'socks5h', applyProxy builds a SOCKS5 dialer with golang.org/x/net/proxy's proxy.FromURL and wraps any failure. This error means the proxy library could not construct a dialer from the parsed URL, typically because the URL's authentication info is malformed or the scheme string is rejected by proxy.FromURL.

Solutions

  1. Inspect the wrapped error (%w) for the underlying cause reported by proxy.FromURL.
  2. Percent-encode the username/password in the SOCKS5 URL, e.g. use url.UserPassword or escape special characters: 'socks5://user:p%40ss@host:1080'.
  3. Test the same URL with proxy.FromURL in isolation to confirm it is constructible.
  4. Update golang.org/x/net to the latest version in go.mod.

Example fix

// before
client, err := NewHTTPClient(WithProxy("socks5://user:p@ss:wrd@127.0.0.1:1080"))

// after
client, err := NewHTTPClient(WithProxy("socks5://user:p%40ss%3Awrd@127.0.0.1:1080"))
Defensive patterns

Strategy: try-catch

Validate before calling

if u, err := url.Parse(cfg.Proxy); err == nil && strings.HasPrefix(u.Scheme, "socks5") {
    if _, err := proxy.FromURL(u, proxy.Direct); err != nil {
        return fmt.Errorf("unusable SOCKS5 proxy: %w", err)
    }
}

Try / catch

if err := NewHTTPClient(WithProxy(socksURL)); err != nil {
    var wrapped error
    if errors.As(err, &wrapped) && strings.Contains(err.Error(), "SOCKS5") {
        // inspect wrapped cause from proxy.FromURL, fix credentials/encoding
    }
    return err
}

Prevention

When it happens

Trigger: NewHTTPClient called with a socks5 proxy URL whose user:password component cannot be used to build auth (e.g. URL-encoded credentials that fail to decode, or an unsupported scheme variant passed to proxy.FromURL).

Common situations: SOCKS5 proxies requiring auth where the password contains special characters not correctly encoded; using a scheme proxy.FromURL does not accept; a dependency version of golang.org/x/net whose FromURL rejects the URL form.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/bbbdc37de35b4624. Report an issue: GitHub.

Appendix: source

Thrown at util/http_util.go:101

	if err != nil {
		return fmt.Errorf("代理地址解析失败: %w", err)
	}
	if proxyURL.Scheme == "" || proxyURL.Host == "" {
		return fmt.Errorf("代理地址必须包含协议和主机")
	}

	switch strings.ToLower(proxyURL.Scheme) {
	case "socks5", "socks5h":
		if proxyURL.Scheme == "socks5h" {
			clone := *proxyURL
			clone.Scheme = "socks5"
			proxyURL = &clone
		}

		// 创建SOCKS5代理拨号器
		dialer, err := proxy.FromURL(proxyURL, proxy.Direct)
		if err != nil {
			return fmt.Errorf("SOCKS5代理初始化失败: %w", err)
		}

		transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
			return dialer.Dial(network, addr)
		}
	case "http", "https":
		// HTTP/HTTPS代理
		transport.Proxy = http.ProxyURL(proxyURL)
	default:
		return fmt.Errorf("不支持的代理协议: %s", proxyURL.Scheme)
	}

	return nil
}

// GetHTTPClient 获取HTTP客户端
func GetHTTPClient() *http.Client {
	if httpClient == nil {

View on GitHub (pinned to beaa561337)