{"record":{"id":"1ad106c94a6fbb42","repo":"fish2018/pansou","slug":"s-w-1ad106","errorCode":null,"errorMessage":"[%s] 创建首页请求失败: %w","messagePattern":"\\[(.+?)\\] 创建首页请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/jsnoteclub/jsnoteclub.go","lineNumber":230,"sourceCode":"\tposts, err := p.fetchPosts(client, dataKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tpostsCache.entries = posts\n\tpostsCache.expire = time.Now().Add(postsCacheTTL)\n\tpostsCache.key = dataKey\n\n\treturn posts, nil\n}\n\nfunc (p *JsNoteClubPlugin) fetchDataKey(client *http.Client) (string, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, \"https://jsnoteclub.com/\", nil)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"[%s] 创建首页请求失败: %w\", p.Name(), err)\n\t}\n\tsetHTMLHeaders(req, \"https://jsnoteclub.com/\")\n\n\tresp, err := p.doRequestWithRetry(req, client, maxRequestRetries)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"[%s] 访问首页失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"[%s] 首页返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"[%s] 解析首页失败: %w\", p.Name(), err)\n\t}\n","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/jsnoteclub/jsnoteclub.go#L212-L248","documentation":"This error is returned by JsNoteClubPlugin.fetchDataKey when http.NewRequestWithContext fails to construct the GET request for https://jsnoteclub.com/. The wrapped error (%w) carries the underlying httpx/net-http construction failure. It means the request could not even be built, before any network I/O happens.","triggerScenarios":"http.NewRequestWithContext returns a non-nil error for the fixed URL https://jsnoteclub.com/ — practically only when the context passed to the request is invalid/dead or the http.Client configuration is broken; with a literal valid URL this almost never fires.","commonSituations":"A parent context that was already cancelled or exceeded its deadline being threaded into context.Background replacement incorrectly; running inside an environment where the http package cannot build requests (rare, e.g. a nil URL from a refactored constant); a build-time regression that changed the hardcoded URL to an unparsable value.","solutions":["Inspect the wrapped error via errors.Unwrap or %v logging to see the exact NewRequest failure reason","Verify no cancelled/expired context is being substituted for context.Background()","Check that the hardcoded URL constant was not modified to an invalid value","Retry the run; if transient environment corruption is suspected, restart the process"],"exampleFix":"// before\nreq, err := http.NewRequestWithContext(ctx, http.MethodGet, \"https://jsnoteclub.com/\", nil)\nif err != nil {\n    return \"\", fmt.Errorf(\"[%s] 创建首页请求失败: %w\", p.Name(), err)\n}\n// after\nreq, err := http.NewRequestWithContext(ctx, http.MethodGet, homepageURL, nil)\nif err != nil {\n    return \"\", fmt.Errorf(\"[%s] 创建首页请求失败: %w (url=%q)\", p.Name(), err, homepageURL)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"key, err := plugin.fetchDataKey(client)\nif err != nil {\n    var reqErr *url.Error\n    if errors.As(err, &reqErr) {\n        // request construction/transport failure: log and skip or retry later\n        return fmt.Errorf(\"skipping jsnoteclub: %w\", err)\n    }\n    return err\n}","preventionTips":["Keep the request URL a validated constant (parse it once with url.Parse at init)","Never thread an already-cancelled context into request construction","Log errors.Unwrap(err) to distinguish construction failures from transport failures"],"tags":["network","http","request-construction"],"backgroundTag":"http-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"}