{"record":{"id":"561236d27ad102e1","repo":"Tencent/WeKnora","slug":"failed-to-marshal-request-w-561236","errorCode":null,"errorMessage":"failed to marshal request: %w","messagePattern":"failed to marshal request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/web_search/tavily.go","lineNumber":75,"sourceCode":"\tctx context.Context,\n\tquery string,\n\tmaxResults int,\n\tincludeDate bool,\n) ([]*types.WebSearchResult, error) {\n\tif len(query) == 0 {\n\t\treturn nil, fmt.Errorf(\"query is empty\")\n\t}\n\tlogger.Infof(ctx, \"[WebSearch][Tavily] query=%q maxResults=%d url=%s\", query, maxResults, p.baseURL)\n\n\treqBody := tavilySearchRequest{\n\t\tAPIKey:     p.apiKey,\n\t\tQuery:      query,\n\t\tMaxResults: maxResults,\n\t}\n\n\tbodyBytes, err := json.Marshal(reqBody)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal request: %w\", err)\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, \"POST\", p.baseURL, bytes.NewReader(bodyBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := p.client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\trespBody, _ := io.ReadAll(resp.Body)\n\t\tlogger.Warnf(ctx, \"[WebSearch][Tavily] API returned status %d: %s\", resp.StatusCode, string(respBody))\n\t\treturn nil, fmt.Errorf(\"tavily API returned status %d: %s\", resp.StatusCode, string(respBody))","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/tavily.go#L57-L93","documentation":"json.Marshal failed while serializing the tavilySearchRequest struct to a request body. This is nearly impossible with the fixed struct (string/int fields), so when it occurs it signals a programming-level issue such as an unsupported field type added to the request struct or a corrupted value (e.g. NaN in a float field) — not a runtime/user problem.","triggerScenarios":"A custom/extended tavilySearchRequest containing a type json.Marshal cannot encode (chan, func, circular reference, NaN/Inf float); the shipped struct cannot realistically trigger this.","commonSituations":"After modifying the request struct to add fields of unsupported types; passing through a struct with invalid float values from upstream data.","solutions":["Inspect the wrapped error for the offending field/type reported by encoding/json","Remove or fix unsupported field types in the request struct (no chan/func/cycles; sanitize NaN floats before marshaling)","If upstream data may contain invalid floats, sanitize or zero them before constructing reqBody","Add a unit test marshaling the request struct to catch regressions"],"exampleFix":"// before\nreqBody := tavilySearchRequest{..., Score: math.NaN()}\n// after\nscore := computedScore\nif math.IsNaN(score) || math.IsInf(score, 0) {\n    score = 0\n}\nreqBody := tavilySearchRequest{..., Score: score}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"bodyBytes, err := json.Marshal(reqBody)\nif err != nil {\n    // log the offending field; this indicates a struct/type bug, not transient failure\n    logger.Errorf(ctx, \"tavily request marshal failed: %v\", err)\n    return nil, err\n}","preventionTips":["Keep only JSON-encodable field types in request structs","Sanitize NaN/Inf floats before marshaling","Add a marshal unit test for the request struct"],"tags":["json","serialization","tavily","programming-error"],"backgroundTag":"json-marshal-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}