fish2018/pansou · error
[ ] 创建首页请求失败
Error message
[%s] 创建首页请求失败: %w
What it means
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.
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
Example fix
// before
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://jsnoteclub.com/", nil)
if err != nil {
return "", fmt.Errorf("[%s] 创建首页请求失败: %w", p.Name(), err)
}
// after
req, err := http.NewRequestWithContext(ctx, http.MethodGet, homepageURL, nil)
if err != nil {
return "", fmt.Errorf("[%s] 创建首页请求失败: %w (url=%q)", p.Name(), err, homepageURL)
} Defensive patterns
Strategy: try-catch
Try / catch
key, err := plugin.fetchDataKey(client)
if err != nil {
var reqErr *url.Error
if errors.As(err, &reqErr) {
// request construction/transport failure: log and skip or retry later
return fmt.Errorf("skipping jsnoteclub: %w", err)
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/1ad106c94a6fbb42.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/jsnoteclub/jsnoteclub.go:230
posts, err := p.fetchPosts(client, dataKey)
if err != nil {
return nil, err
}
postsCache.entries = posts
postsCache.expire = time.Now().Add(postsCacheTTL)
postsCache.key = dataKey
return posts, nil
}
func (p *JsNoteClubPlugin) fetchDataKey(client *http.Client) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://jsnoteclub.com/", nil)
if err != nil {
return "", fmt.Errorf("[%s] 创建首页请求失败: %w", p.Name(), err)
}
setHTMLHeaders(req, "https://jsnoteclub.com/")
resp, err := p.doRequestWithRetry(req, client, maxRequestRetries)
if err != nil {
return "", fmt.Errorf("[%s] 访问首页失败: %w", p.Name(), err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("[%s] 首页返回状态码: %d", p.Name(), resp.StatusCode)
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return "", fmt.Errorf("[%s] 解析首页失败: %w", p.Name(), err)
}
View on GitHub (pinned to beaa561337)