fish2018/pansou · error

[ ] 创建内容请求失败

Error message

[%s] 创建内容请求失败: %w

What it means

This error is returned by fetchPosts in the jsnoteclub plugin when http.NewRequestWithContext fails to construct the GET request for the Ghost Content API (https://jsnoteclub.com/ghost/api/content/posts/). With a constant, hard-coded URL and no request body, this essentially only fails on invalid URL parsing or a nil context, making it a near-impossible internal failure that surfaces wrapped with the plugin name. It aborts the search before any network call is made.

Solutions

  1. Check the URL string being passed to http.NewRequestWithContext — print/log it and validate with url.Parse; fix any malformed characters (spaces, unescaped symbols).
  2. Verify the context passed in is non-nil; use context.WithTimeout(context.Background(), ...) as the source does.
  3. Revert any local modifications to the hard-coded posts URL constant in jsnoteclub.go.
  4. Since the error wraps the original err with %w, inspect errors.Unwrap(err) to see the exact url.Error cause.

Example fix

// before
reqURL := fmt.Sprintf("https://jsnoteclub.com/ghost/api/content/posts/?%s", params.Encode())
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
// after
reqURL := fmt.Sprintf("https://jsnoteclub.com/ghost/api/content/posts/?%s", params.Encode())
if _, perr := url.Parse(reqURL); perr != nil {
    return nil, fmt.Errorf("invalid posts URL %q: %w", reqURL, perr)
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: validate the URL before building the request
if _, err := url.Parse("https://jsnoteclub.com/ghost/api/content/posts/"); err != nil {
    return fmt.Errorf("invalid posts URL: %w", err)
}
if ctx == nil {
    return fmt.Errorf("context must not be nil")
}

Try / catch

posts, err := p.fetchPosts(client, dataKey)
if err != nil {
    log.Printf("jsnoteclub fetchPosts failed: %v", err)
    return nil, err
}

Prevention

When it happens

Trigger: http.NewRequestWithContext returns an error while building the posts API request — practically only if the constructed URL (base URL + url.Values query string) fails url.Parse, or the context is nil. In this code path the URL is constant and the context is always valid, so it is effectively unreachable in normal operation.

Common situations: Developers hit this when forking/modifying the plugin: changing the base URL to a malformed value, injecting user-supplied data into the URL string without escaping, or refactoring the context handling so a nil context is passed.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at plugin/jsnoteclub/jsnoteclub.go:278

	return match[1], nil
}

func (p *JsNoteClubPlugin) fetchPosts(client *http.Client, dataKey string) ([]ghostPost, error) {
	params := url.Values{}
	params.Set("key", dataKey)
	params.Set("limit", "10000")
	params.Set("fields", "id,slug,title,excerpt,url,updated_at,visibility")
	params.Set("order", "updated_at DESC")

	reqURL := fmt.Sprintf("https://jsnoteclub.com/ghost/api/content/posts/?%s", params.Encode())

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
	if err != nil {
		return nil, fmt.Errorf("[%s] 创建内容请求失败: %w", p.Name(), err)
	}
	setAPIHeaders(req, "https://jsnoteclub.com/")

	resp, err := p.doRequestWithRetry(req, client, maxRequestRetries)
	if err != nil {
		return nil, fmt.Errorf("[%s] 获取内容失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("[%s] 内容接口返回状态码: %d", p.Name(), resp.StatusCode)
	}

	var payload ghostPostsResponse
	if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
		return nil, fmt.Errorf("[%s] 解析内容数据失败: %w", p.Name(), err)
	}

View on GitHub (pinned to beaa561337)