fish2018/pansou · error
创建SOCKS5代理失败
Error message
创建SOCKS5代理失败: %w
What it means
If the configured proxy URL has scheme socks5, the plugin calls golang.org/x/net/proxy.FromURL to build a SOCKS5 dialer. FromURL returns an error when it cannot construct the dialer — most commonly an unknown scheme (the socks5 dialer must be registered, e.g. via an import of x/net/proxy/socks5) or invalid embedded credentials — and the plugin wraps it as '创建SOCKS5代理失败: %w'.
Solutions
- Ensure the socks5 dialer is registered: import _ "golang.org/x/net/proxy/socks5" so proxy.FromURL recognizes the socks5 scheme.
- Check the wrapped %w error; if it says unknown scheme, fix the scheme spelling (socks5, not sock5/socks) or register a custom dialer.
- URL-encode username/password in the proxy URL (url.QueryEscape) if credentials contain special characters.
- If the proxy is actually HTTP, use scheme http:// instead of socks5:// so the non-socks branch builds the transport.
Example fix
// before (dialer unknown)
import "golang.org/x/net/proxy"
// after
import (
"golang.org/x/net/proxy"
_ "golang.org/x/net/proxy/socks5" // registers socks5/socks5h schemes
) Defensive patterns
Strategy: try-catch
Validate before calling
// verify the socks5 dialer is available before configuring the proxy
if strings.HasPrefix(strings.ToLower(cfg.ProxyURL), "socks5") {
u, _ := url.Parse(cfg.ProxyURL)
if _, err := proxy.FromURL(u, proxy.Direct); err != nil {
return fmt.Errorf("socks5 dialer unavailable: %w", err)
}
} Try / catch
transport, err := buildProxyTransport(cfg)
if err != nil && strings.Contains(err.Error(), "创建SOCKS5代理失败") {
log.Warn("SOCKS5 proxy unavailable, using direct connection")
transport, err = buildPlainTransport(cfg)
} Prevention
- Keep the blank import _ "golang.org/x/net/proxy/socks5" so proxy.FromURL supports socks5 schemes.
- Pin/upgrade golang.org/x/net deliberately and re-test SOCKS5 after upgrades.
- Encode proxy auth credentials properly; test with a real socks5 proxy in CI.
- Confirm the proxy actually speaks SOCKS5 before setting the socks5:// scheme.
When it happens
Trigger: ProxyURL scheme is socks5 (or socks5h) and proxy.FromURL fails: typically because the x/net/proxy/socks5 package isn't linked (FromURL returns 'proxy: unknown scheme' for socks5 without a registered dialer), or the userinfo (username/password) in the URL is invalid/undecodable.
Common situations: Project missing the blank import _ "golang.org/x/net/proxy/socks5"; proxy requires auth and credentials contain characters needing escaping; user set socks5:// but the proxy is actually HTTP; typo like sock5:// handled elsewhere.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/d4bbcc5bcc3baab3.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/gying/gying.go:1640
if !baseTransportField.IsValid() || baseTransportField.IsNil() {
return fmt.Errorf("未找到底层 transport")
}
baseTransportValue := reflect.NewAt(baseTransportField.Type(), unsafe.Pointer(baseTransportField.UnsafeAddr())).Elem()
baseTransport, ok := baseTransportValue.Interface().(*http.Transport)
if !ok || baseTransport == nil {
return fmt.Errorf("底层 transport 无效")
}
proxyURL, err := url.Parse(config.AppConfig.ProxyURL)
if err != nil {
return fmt.Errorf("解析代理地址失败: %w", err)
}
if proxyURL.Scheme == "socks5" {
dialer, err := proxy.FromURL(proxyURL, proxy.Direct)
if err != nil {
return fmt.Errorf("创建SOCKS5代理失败: %w", err)
}
baseTransport.Proxy = nil
baseTransport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
return dialer.Dial(network, addr)
}
} else {
baseTransport.Proxy = http.ProxyURL(proxyURL)
}
if DebugLog {
fmt.Printf("[Gying] 已应用代理到scraper: %s\n", config.AppConfig.ProxyURL)
}
return nil
}
func (p *GyingPlugin) solveBotChallenge(scraper *cloudscraper.Scraper, requestURL string, body []byte) error {
matches := challengeJSONPattern.FindSubmatch(body)View on GitHub (pinned to beaa561337)