{"record":{"id":"ea7563e935e07116","repo":"fish2018/pansou","slug":"s-w-ea7563","errorCode":null,"errorMessage":"[%s] 会话请求失败: %w","messagePattern":"\\[(.+?)\\] 会话请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/nsgame/nsgame.go","lineNumber":365,"sourceCode":"\nfunc (p *NSGameAsyncPlugin) postSessionRaw(client *http.Client, path string, body []byte) ([]byte, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)\n\tdefer cancel()\n\tvar reader io.Reader\n\tif body != nil {\n\t\treader = strings.NewReader(string(body))\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, baseURL+path, reader)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建会话请求失败: %w\", p.Name(), err)\n\t}\n\tif body != nil {\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t}\n\tp.setRequestHeaders(req, \"https://nsthwj.cn/\")\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 会话请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\tdata, _ := io.ReadAll(resp.Body)\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"[%s] 会话返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\treturn data, nil\n}\n\nfunc solveChallenge(challenge string, difficultyBits int) string {\n\tfor nonce := int64(0); nonce < 10000000; nonce++ {\n\t\tsum := sha256.Sum256([]byte(fmt.Sprintf(\"%s:%d\", challenge, nonce)))\n\t\tfullBytes, remainder := difficultyBits/8, difficultyBits%8\n\t\tvalid := true\n\t\tfor i := 0; i < fullBytes; i++ {\n\t\t\tif sum[i] != 0 {\n\t\t\t\tvalid = false\n\t\t\t\tbreak","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/nsgame/nsgame.go#L347-L383","documentation":"nsgame's postSessionRaw wraps any error returned by the HTTP client's Do() when POSTing to the session endpoints (/traffic/session/challenge or /traffic/session/issue). It prefixes the plugin name and the Chinese text '会话请求失败' (session request failed) and preserves the underlying error via %w. This means the request never got an HTTP response at all — it failed at the transport level (DNS, TCP, TLS, timeout, or context cancellation).","triggerScenarios":"p.postSessionRaw calls client.Do(req) and err != nil: DNS resolution failure for nsthwj.cn, TCP connect failure, TLS handshake failure, context/deadline exceeded, or connection reset before any response bytes arrive. Raised from ensureSession (challenge/issue calls) and postSession.","commonSituations":"Target site nsthwj.cn is down or blocked (GFW/regional block), no network in a container, missing proxy config, TLS cert issues with a MITM proxy, or the site drops long-lived connections so a stale client fails.","solutions":["Check basic connectivity to the site: curl -v https://nsthwj.cn/ from the machine running the plugin.","Unwrap the error with errors.Unwrap or inspect with errors.As(*url.Error)/net.Error to see the root cause (timeout vs DNS vs TLS).","Configure a proxy (HTTP_PROXY/HTTPS_PROXY or the plugin's client transport) if the site is unreachable from your network.","Increase the http.Client Timeout if errors.As reveals context deadline exceeded on slow endpoints.","Retry with backoff; transient connection resets are common with such sites."],"exampleFix":"// before\nresp, err := client.Do(req)\nif err != nil {\n    return nil, fmt.Errorf(\"[%s] 会话请求失败: %w\", p.Name(), err)\n}\n// after\nresp, err := client.Do(req)\nif err != nil {\n    var nerr net.Error\n    if errors.As(err, &nerr) && nerr.Timeout() {\n        return nil, fmt.Errorf(\"[%s] 会话请求超时: %w\", p.Name(), err)\n    }\n    return nil, fmt.Errorf(\"[%s] 会话请求失败: %w\", p.Name(), err)\n}","handlingStrategy":"retry","validationCode":"// preflight\nif _, err := net.LookupHost(\"nsthwj.cn\"); err != nil { return fmt.Errorf(\"DNS 解析失败: %w\", err) }","typeGuard":"var nerr net.Error\nisNetworkTimeout := errors.As(err, &nerr) && nerr.Timeout()","tryCatchPattern":"data, err := p.postSessionRaw(client, path, body)\nif err != nil {\n    var nerr net.Error\n    if errors.As(err, &nerr) && nerr.Timeout() {\n        // retry with backoff\n    } else {\n        return fmt.Errorf(\"session transport failed: %w\", err)\n    }\n}","preventionTips":["Set a sane http.Client Timeout and retry transport errors with exponential backoff.","Configure proxy environment variables when the target site is region-blocked.","Monitor DNS/connectivity from the deployment host before blaming the plugin.","Reuse a single shared http.Client with keep-alives to avoid stale-connection failures."],"tags":["network","http-client","go","plugin"],"backgroundTag":"network-request-failed","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}