{"record":{"id":"6ec58b8cd89f9201","repo":"fish2018/pansou","slug":"s-6ec58b","errorCode":null,"errorMessage":"盘链列表接口异常: %s","messagePattern":"盘链列表接口异常: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/panlian/panlian.go","lineNumber":825,"sourceCode":"\t}\n\n\treturn links, strings.Join(summaryParts, \" / \"), latest, truncated\n}\n\nfunc (p *PanlianPlugin) fetchVideos(client *http.Client, cookie string, keyword string) (*VideoSearchResponse, error) {\n\tvalues := url.Values{}\n\tvalues.Set(\"wd\", keyword)\n\tvalues.Set(\"pg\", \"1\")\n\n\tvar resp VideoSearchResponse\n\tif err := p.doJSONGET(client, cookie, \"/api/get_videos.php\", values, &resp); err != nil {\n\t\treturn nil, err\n\t}\n\tif resp.Code == -1 && strings.Contains(resp.Msg, \"登录\") {\n\t\treturn nil, fmt.Errorf(\"%w: %s\", errLoginRequired, resp.Msg)\n\t}\n\tif resp.Code != 1 {\n\t\treturn nil, fmt.Errorf(\"盘链列表接口异常: %s\", resp.Msg)\n\t}\n\treturn &resp, nil\n}\n\nfunc (p *PanlianPlugin) fetchPanLinks(client *http.Client, cookie string, keyword string, vodID int) (*PanLinkResponse, error) {\n\tvalues := url.Values{}\n\tvalues.Set(\"keyword\", keyword)\n\tvalues.Set(\"vod_id\", fmt.Sprintf(\"%d\", vodID))\n\tvalues.Set(\"_t\", fmt.Sprintf(\"%d\", time.Now().UnixMilli()))\n\n\tvar resp PanLinkResponse\n\tif err := p.doJSONGET(client, cookie, \"/api/search_pan_links.php\", values, &resp); err != nil {\n\t\treturn nil, err\n\t}\n\tif !resp.Success && strings.Contains(resp.Message, \"登录\") {\n\t\treturn nil, fmt.Errorf(\"%w: %s\", errLoginRequired, resp.Message)\n\t}\n\tif !resp.Success {","sourceCodeStart":807,"sourceCodeEnd":843,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panlian/panlian.go#L807-L843","documentation":"When the panlian /api/get_videos.php response returns a Code other than 1 (and it is not the login case), the plugin rejects it with '盘链列表接口异常: <Msg>' ('panlian list API abnormal'). It means the API responded but with an unexpected business-level failure code.","triggerScenarios":"Upstream returns Code != 1: keyword rejected, account quota/ban, server-side error, API version mismatch, or empty/no-results encoded as a failure code.","commonSituations":"Searching during panlian maintenance windows; account restricted for abuse; panlian upgraded its API and changed success semantics; unusual keywords triggering server-side filters.","solutions":["Read the Msg included in the error to identify the upstream-reported cause.","Retry later if the message indicates server-side trouble/maintenance.","Check your panlian account status (ban/quota) on the site.","Update the plugin if panlian changed its API response codes."],"exampleFix":"// before\nresp, err := fetchVideos(kw) // 盘链列表接口异常: 服务繁忙\n// after\nresp, err := fetchVideos(kw)\nif err != nil && strings.Contains(err.Error(), \"服务繁忙\") {\n    time.Sleep(retryBackoff); resp, err = fetchVideos(kw)\n}","handlingStrategy":"retry","validationCode":"// normalize keyword before the API call\nkw = strings.TrimSpace(keyword)\nif kw == \"\" || len([]rune(kw)) > 100 {\n    return fmt.Errorf(\"invalid keyword %q for panlian search\", keyword)\n}","typeGuard":null,"tryCatchPattern":"resp, err := plugin.SearchVideos(ctx, keyword)\nif err != nil && strings.Contains(err.Error(), \"盘链列表接口异常\") {\n    select {\n    case <-time.After(backoff):\n        resp, err = plugin.SearchVideos(ctx, keyword) // retry once\n    }\n}","preventionTips":["Rate-limit outbound panlian requests to avoid server-side rejections.","Log the full upstream Msg carried in the error for diagnosis.","Check panlian account status/quota periodically.","Track panlian API announcements for code-semantics changes."],"tags":["api","upstream-api","error-response","search"],"backgroundTag":"api-error-response","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"}