{"record":{"id":"9675f1b7f27784f7","repo":"fish2018/pansou","slug":"s-hsid-s-json-w","errorCode":null,"errorMessage":"[%s] hsid=%s链接JSON解析失败: %w","messagePattern":"\\[(.+?)\\] hsid=(.+?)链接JSON解析失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/haisou/haisou.go","lineNumber":421,"sourceCode":"\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接请求失败: %w\", p.Name(), hsid, err)\n\t}\n\tdefer resp.Body.Close()\n\n\t// 检查状态码\n\tif resp.StatusCode != 200 {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接请求返回状态码: %d\", p.Name(), hsid, resp.StatusCode)\n\t}\n\n\t// 读取响应体\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s读取响应失败: %w\", p.Name(), hsid, err)\n\t}\n\n\t// 解析响应\n\tvar apiResp FetchAPIResponse\n\tif err := json.Unmarshal(body, &apiResp); err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接JSON解析失败: %w\", p.Name(), hsid, err)\n\t}\n\n\t// 检查API响应状态\n\tif apiResp.Code != 0 {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接API错误: %s\", p.Name(), hsid, apiResp.Msg)\n\t}\n\n\t// 根据平台类型构建完整的分享链接\n\tshareURL := buildShareURL(platform, apiResp.Data.ShareCode)\n\tif shareURL == \"\" {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s不支持的网盘平台: %s\", p.Name(), hsid, platform)\n\t}\n\n\t// 获取密码\n\tpassword := \"\"\n\tif apiResp.Data.SharePwd != nil {\n\t\tpassword = *apiResp.Data.SharePwd\n\t}","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/haisou/haisou.go#L403-L439","documentation":"This error is thrown by fetchShareLink when the fetched share-link response body cannot be unmarshalled into FetchAPIResponse. Like the search-page variant, it means the upstream returned malformed or structurally unexpected JSON (often an HTML/anti-bot page) despite HTTP 200.","triggerScenarios":"json.Unmarshal(body, &apiResp) fails in fetchShareLink — body is not valid JSON for FetchAPIResponse (wrong types, truncated body, HTML error content).","commonSituations":"Anti-bot/WAF page returned with HTTP 200; API schema drift (field type changed); response truncated by proxy; Captcha challenge page served as HTML.","solutions":["Log the raw body (truncated) alongside the unmarshal error to see what was actually returned","Verify FetchAPIResponse struct matches the current API schema","Check whether haisou.cc is serving HTML/captcha to your IP (curl the endpoint)","Sniff the first non-whitespace byte — non-'{' bodies are HTML, skip unmarshalling and retry/flag"],"exampleFix":"// before\nvar apiResp FetchAPIResponse\nif err := json.Unmarshal(body, &apiResp); err != nil {\n\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接JSON解析失败: %w\", p.Name(), hsid, err)\n}\n// after\ntrimmed := bytes.TrimSpace(body)\nif len(trimmed) == 0 || trimmed[0] != '{' {\n\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s返回非JSON响应(疑似反爬页面): %.100s\", p.Name(), hsid, string(trimmed))\n}\nvar apiResp FetchAPIResponse\nif err := json.Unmarshal(trimmed, &apiResp); err != nil {\n\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接JSON解析失败: %w\", p.Name(), hsid, err)\n}","handlingStrategy":"type-guard","validationCode":"trimmed := bytes.TrimSpace(body)\nif len(trimmed) == 0 || trimmed[0] != '{' {\n\treturn errors.New(\"response is not JSON (likely HTML/anti-bot page)\")\n}\nif !json.Valid(trimmed) {\n\treturn errors.New(\"response body is not valid JSON\")\n}","typeGuard":"func isJSONBody(b []byte) bool {\n\tt := bytes.TrimSpace(b)\n\treturn len(t) > 0 && t[0] == '{' && json.Valid(t)\n}","tryCatchPattern":"var apiResp FetchAPIResponse\nif err := json.Unmarshal(body, &apiResp); err != nil {\n\tlog.Printf(\"share link parse failed, head: %.200s\", body)\n\treturn fmt.Errorf(\"share link JSON parse failed: %w\", err)\n}","preventionTips":["Detect HTML/anti-bot pages before unmarshalling","Keep FetchAPIResponse in sync with the live API schema","Log truncated bodies on failure for diagnosis","Treat repeated parse failures as an upstream health signal and back off"],"tags":["json","unmarshal","api-response","go"],"backgroundTag":"json-unmarshal-failed","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"}