fish2018/pansou · error
JWT Payload中没有链接
Error message
JWT Payload中没有链接
What it means
After successfully unmarshalling the JWT payload, decodeJWTURL checks that data.url is a non-empty string. This error is thrown when the JSON parsed fine but contains no usable link at data.url — the struct fields remain zero-valued. It is a domain validation that the decoded token actually carries a redirect target.
Solutions
- Dump the decoded payload JSON to confirm where the URL actually lives and update the struct path (data.url vs url vs target).
- Treat such tokens as invalid inputs and skip/refresh them from the source page instead of decoding.
- Add an upstream schema check: fetch a fresh token and verify it contains data.url before relying on cached behavior.
- If the URL legitimately may be empty, return the error to callers but make the message point at the missing field for faster diagnosis.
Example fix
// before
if strings.TrimSpace(payloadData.Data.URL) == "" {
return "", fmt.Errorf("JWT Payload中没有链接")
}
// after: point at the actual payload for diagnosis
if strings.TrimSpace(payloadData.Data.URL) == "" {
return "", fmt.Errorf("JWT Payload中没有链接 (payload=%s)", string(payload))
} Defensive patterns
Strategy: validation
Validate before calling
var probe struct {
Data struct {
URL string `json:"url"`
} `json:"data"`
}
if err := json.Unmarshal(payload, &probe); err != nil {
return err
}
if strings.TrimSpace(probe.Data.URL) == "" {
return errors.New("token payload carries no url — skip this item")
} Type guard
func payloadHasURL(payload []byte) bool {
var p struct {
Data struct {
URL string `json:"url"`
} `json:"data"`
}
if json.Unmarshal(payload, &p) != nil {
return false
}
return strings.TrimSpace(p.Data.URL) != ""
} Try / catch
url, err := decodeJWTURL(jwtToken)
if errors.Is(err, errNoLinkInPayload) || strings.Contains(err.Error(), "没有链接") {
log.Printf("token %s… has no embedded link, skipping item", jwtToken[:12])
continue
}
if err != nil {
return err
} Prevention
- Validate that a button element actually carries a link-bearing token before decoding.
- Spot-check payloads after upstream site changes; the URL may move to a different JSON path.
- Skip and refresh empty-URL tokens rather than retrying them forever.
- Cache only successfully decoded, non-empty URLs.
When it happens
Trigger: getButtonDetail passes a JWT whose payload JSON parses but has an empty or missing data.url field, e.g. {"data":{"url":""}} or a payload with other claims only.
Common situations: Upstream site issues tokens without embedded links for certain buttons (login/dead buttons); the payload schema changed so the URL now sits at a different JSON path; whitespace-only url values (TrimSpace catches those too).
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- username cannot be empty
- token cannot be empty
- secret cannot be empty
- unexpected signing method
- invalid token
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/7aa84a81c730b50d.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/susu/susu.go:536
}
// 解码Payload
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return "", fmt.Errorf("解码Payload失败: %w", err)
}
// 解析JSON
var payloadData struct {
Data struct {
URL string `json:"url"`
} `json:"data"`
}
if err := json.Unmarshal(payload, &payloadData); err != nil {
return "", fmt.Errorf("解析Payload JSON失败: %w", err)
}
if strings.TrimSpace(payloadData.Data.URL) == "" {
return "", fmt.Errorf("JWT Payload中没有链接")
}
// 缓存结果
jwtDecodeCache.Store(jwtToken, payloadData.Data.URL)
return payloadData.Data.URL, nil
}
func setBrowserHeaders(req *http.Request, referer string) {
req.Header.Set("User-Agent", getRandomUA())
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Referer", referer)
}
func setAPIHeaders(req *http.Request, referer string) {
setBrowserHeaders(req, referer)
req.Header.Set("Accept", "application/json, text/plain, */*")View on GitHub (pinned to beaa561337)