fish2018/pansou · error
站点地址不能包含参数或锚点
Error message
站点地址不能包含参数或锚点
What it means
This error comes from the gying plugin's base-URL validation (normalizeSiteURL around plugin/gying.go:615). It fires when the configured site address, after url.Parse, still carries a query string (?...) or a fragment (#...). The plugin expects a bare origin like https://example.com because requests are built internally by appending fixed API paths.
Solutions
- Remove the query string and fragment, keeping only scheme://host (e.g. https://example.com).
- If the URL came from a browser, copy the origin up to and including the TLD, dropping everything after '?' or '#'.
- Re-save the plugin config and restart/reload the plugin.
Example fix
// before
p.saveConfig("https://example.com/?utm_source=bar#main")
// after
p.saveConfig("https://example.com") Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(siteURL)
if err != nil || u.Host == "" { return fmt.Errorf("invalid site URL") }
if u.RawQuery != "" || u.Fragment != "" || (u.Path != "" && u.Path != "/") { return fmt.Errorf("site URL must be a bare origin") } Type guard
func isBareOrigin(raw string) bool {
u, err := url.Parse(raw)
return err == nil && u.Host != "" && u.RawQuery == "" && u.Fragment == "" && (u.Path == "" || u.Path == "/")
} Try / catch
baseURL, err := normalizeSiteURL(input)
if err != nil {
log.Printf("invalid site URL %q: %v", input, err)
return err
} Prevention
- Copy only the origin (scheme://host) from the browser, not the full page URL.
- Strip query and fragment in your UI before saving the config.
- Add a client-side URL field validator rejecting '?', '#', and path suffixes.
When it happens
Trigger: Calling the plugin's config/set-URL path with a value such as https://example.com/?src=app or https://example.com/#top; pasting a URL copied from a browser address bar that includes tracking query params or an anchor.
Common situations: Users paste a full page URL (with search params or section anchors) into the plugin's site-address config field instead of the site origin.
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/b64ed20c4f4b15b5.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/gying/gying.go:615
if baseURL == "" {
return "", fmt.Errorf("站点地址不能为空")
}
if !strings.HasPrefix(baseURL, "http://") && !strings.HasPrefix(baseURL, "https://") {
baseURL = "https://" + baseURL
}
parsed, err := url.Parse(baseURL)
if err != nil {
return "", fmt.Errorf("站点地址格式错误: %v", err)
}
if parsed.Scheme != "http" && parsed.Scheme != "https" {
return "", fmt.Errorf("站点地址必须以 http:// 或 https:// 开头")
}
if parsed.Host == "" {
return "", fmt.Errorf("站点地址缺少域名")
}
if parsed.RawQuery != "" || parsed.Fragment != "" {
return "", fmt.Errorf("站点地址不能包含参数或锚点")
}
if parsed.Path != "" && parsed.Path != "/" {
return "", fmt.Errorf("站点地址不能包含路径")
}
// HTTP clients do not consistently convert Unicode hostnames to IDNA.
// Store the ASCII form so both the config page and requests are reliable.
hostname, err := idna.Lookup.ToASCII(parsed.Hostname())
if err != nil {
return "", fmt.Errorf("站点域名格式错误: %v", err)
}
host := hostname
if port := parsed.Port(); port != "" {
host += ":" + port
}
return parsed.Scheme + "://" + host, nil
}
View on GitHub (pinned to beaa561337)