{"record":{"id":"0746086ad7abb24f","repo":"fish2018/pansou","slug":"marshal-request-failed-w","errorCode":null,"errorMessage":"marshal request failed: %w","messagePattern":"marshal request failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/jikepan/jikepan.go","lineNumber":70,"sourceCode":"// doSearch 实际的搜索实现\nfunc (p *JikepanAsyncV2Plugin) doSearch(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {\n\t// 构建请求\n\treqBody := map[string]interface{}{\n\t\t\"name\":   keyword,\n\t\t\"is_all\": false,\n\t}\n\t\n\t// 检查ext中是否包含自定义参数，如果有则使用它\n\tif ext != nil {\n\t\tif isAll, ok := ext[\"is_all\"].(bool); ok && isAll {\n\t\t\t// 使用全量搜索，时间大约10秒\n\t\t\treqBody[\"is_all\"] = true\n\t\t}\n\t}\n\t\n\tjsonData, err := json.Marshal(reqBody)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal request failed: %w\", err)\n\t}\n\t\n\treq, err := http.NewRequest(\"POST\", JikepanAPIURL, bytes.NewBuffer(jsonData))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create request failed: %w\", err)\n\t}\n\t\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"referer\", \"https://jikepan.xyz/\")\n\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\")\n\t\n\t// 发送请求\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"request failed: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\t","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/jikepan/jikepan.go#L52-L88","documentation":"doSearch builds the Jikepan API request body as a map and serializes it with json.Marshal before POSTing. If marshaling fails, the error is wrapped as \"marshal request failed\" and doSearch returns no results.","triggerScenarios":"json.Marshal(reqBody) returns an error — practically only when the dynamically-built reqBody map contains a value json cannot encode (e.g. a channel, func, or cyclic value inserted via ext options like is_all handling).","commonSituations":"A caller-supplied ext/option value of an unsupported type ends up in reqBody; custom marshaler on a field returns an error; otherwise extremely rare since map[string]interface{} of plain scalars always marshals.","solutions":["Inspect the wrapped %w error to identify which value failed to marshal","Restrict reqBody values to JSON-safe types (string, bool, number)","Validate/sanitize ext-derived options before inserting them into reqBody"],"exampleFix":"// before\njsonData, err := json.Marshal(reqBody)\nif err != nil {\n\treturn nil, fmt.Errorf(\"marshal request failed: %w\", err)\n}\n\n// after\nif _, ok := reqBody[\"keyword\"].(string); !ok || reqBody[\"keyword\"] == \"\" {\n\treturn nil, fmt.Errorf(\"invalid keyword for jikepan request\")\n}\njsonData, err := json.Marshal(reqBody)\nif err != nil {\n\treturn nil, fmt.Errorf(\"marshal request failed: %w\", err)\n}","handlingStrategy":"validation","validationCode":"kw, ok := ext[\"keyword\"].(string)\nif !ok || strings.TrimSpace(kw) == \"\" {\n\treturn fmt.Errorf(\"jikepan: keyword must be a non-empty string\")\n}","typeGuard":"func isJSONSafe(v interface{}) bool {\n\tswitch v.(type) {\n\tcase nil, string, bool, int, int64, float64, []interface{}, map[string]interface{}:\n\t\treturn true\n\t}\n\treturn false\n}","tryCatchPattern":"// Go\nresults, err := p.doSearch(ctx, keyword, ext)\nvar merr *json.MarshalTypeError\nif errors.As(err, &merr) {\n\tlog.Printf(\"jikepan: unencodable value at %v\", merr.Value)\n\treturn nil, err\n}","preventionTips":["Only put JSON-native types into reqBody","Sanitize ext options before use","Define reqBody as a typed struct instead of map[string]interface{}"],"tags":["json","serialization","request"],"backgroundTag":"json-marshal-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"}