{"record":{"id":"7aa84a81c730b50d","repo":"fish2018/pansou","slug":"jwt-payload","errorCode":null,"errorMessage":"JWT Payload中没有链接","messagePattern":"JWT Payload中没有链接","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/susu/susu.go","lineNumber":536,"sourceCode":"\t}\n\n\t// 解码Payload\n\tpayload, err := base64.RawURLEncoding.DecodeString(parts[1])\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"解码Payload失败: %w\", err)\n\t}\n\n\t// 解析JSON\n\tvar payloadData struct {\n\t\tData struct {\n\t\t\tURL string `json:\"url\"`\n\t\t} `json:\"data\"`\n\t}\n\tif err := json.Unmarshal(payload, &payloadData); err != nil {\n\t\treturn \"\", fmt.Errorf(\"解析Payload JSON失败: %w\", err)\n\t}\n\tif strings.TrimSpace(payloadData.Data.URL) == \"\" {\n\t\treturn \"\", fmt.Errorf(\"JWT Payload中没有链接\")\n\t}\n\n\t// 缓存结果\n\tjwtDecodeCache.Store(jwtToken, payloadData.Data.URL)\n\n\treturn payloadData.Data.URL, nil\n}\n\nfunc setBrowserHeaders(req *http.Request, referer string) {\n\treq.Header.Set(\"User-Agent\", getRandomUA())\n\treq.Header.Set(\"Accept\", \"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\")\n\treq.Header.Set(\"Accept-Language\", \"zh-CN,zh;q=0.9,en;q=0.8\")\n\treq.Header.Set(\"Referer\", referer)\n}\n\nfunc setAPIHeaders(req *http.Request, referer string) {\n\tsetBrowserHeaders(req, referer)\n\treq.Header.Set(\"Accept\", \"application/json, text/plain, */*\")","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/susu/susu.go#L518-L554","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before\nif strings.TrimSpace(payloadData.Data.URL) == \"\" {\n    return \"\", fmt.Errorf(\"JWT Payload中没有链接\")\n}\n// after: point at the actual payload for diagnosis\nif strings.TrimSpace(payloadData.Data.URL) == \"\" {\n    return \"\", fmt.Errorf(\"JWT Payload中没有链接 (payload=%s)\", string(payload))\n}","handlingStrategy":"validation","validationCode":"var probe struct {\n    Data struct {\n        URL string `json:\"url\"`\n    } `json:\"data\"`\n}\nif err := json.Unmarshal(payload, &probe); err != nil {\n    return err\n}\nif strings.TrimSpace(probe.Data.URL) == \"\" {\n    return errors.New(\"token payload carries no url — skip this item\")\n}","typeGuard":"func payloadHasURL(payload []byte) bool {\n    var p struct {\n        Data struct {\n            URL string `json:\"url\"`\n        } `json:\"data\"`\n    }\n    if json.Unmarshal(payload, &p) != nil {\n        return false\n    }\n    return strings.TrimSpace(p.Data.URL) != \"\"\n}","tryCatchPattern":"url, err := decodeJWTURL(jwtToken)\nif errors.Is(err, errNoLinkInPayload) || strings.Contains(err.Error(), \"没有链接\") {\n    log.Printf(\"token %s… has no embedded link, skipping item\", jwtToken[:12])\n    continue\n}\nif err != nil {\n    return err\n}","preventionTips":["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."],"tags":["jwt","validation","missing-field","go"],"backgroundTag":"empty-required-field","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"}