{"record":{"id":"ccd3f71175ce3b0c","repo":"vxcontrol/pentagi","slug":"failed-to-marshal-request-body-v-ccd3f7","errorCode":null,"errorMessage":"failed to marshal request body: %v","messagePattern":"failed to marshal request body: (.+?)","errorType":"exception","errorClass":"Fatal","httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/searchers/traversaal.go","lineNumber":83,"sourceCode":"\t\treturn \"\", err\n\t}\n\n\treturn result, nil\n}\n\nfunc (t *traversaal) search(ctx context.Context, query string) (string, error) {\n\tclient, err := system.GetHTTPClient(t.cfg)\n\tif err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"failed to create http client: %w\", err))\n\t}\n\n\treqBody, err := json.Marshal(struct {\n\t\tQuery string `json:\"query\"`\n\t}{\n\t\tQuery: query,\n\t})\n\tif err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"failed to marshal request body: %v\", err))\n\t}\n\n\treq, err := http.NewRequest(http.MethodPost, traversaalURL, bytes.NewBuffer(reqBody))\n\tif err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"failed to build request: %v\", err))\n\t}\n\n\treq = req.WithContext(ctx)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"x-api-key\", t.apiKey())\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn \"\", Retryable(fmt.Errorf(\"failed to do request: %v\", err), 0)\n\t}\n\tdefer resp.Body.Close()\n\n\treturn t.parseHTTPResponse(resp)","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/searchers/traversaal.go#L65-L101","documentation":"traversaal.search returns Fatal 'failed to marshal request body: %v' when json.Marshal of the {\"query\": string} payload fails. With a plain string field this is practically unreachable — encoding a struct with one string cannot fail — so its presence signals something unusual (custom MarshalJSON, memory corruption, or refactor to complex types).","triggerScenarios":"json.Marshal(struct{ Query string `json:\"query\"` }{Query: query}) returns an error before building the http.Request in search().","commonSituations":"A refactor added unsupported types (channels, funcs, cyclic pointers) to the request struct; extremely rare for the current one-field struct; custom marshaling bugs after extending the payload.","solutions":["Inspect the wrapped %v message for the unsupported type name.","Remove non-serializable fields (channels, funcs, cycles) from the request struct.","Add a unit test marshaling a representative request payload.","No runtime fix needed for the current single-string struct — treat occurrences as a code bug."],"exampleFix":"// before: unsupported field added\nstruct{ Query string; CB chan int `json:\"-\"` }\n// after: keep payload JSON-serializable only\nstruct{ Query string `json:\"query\"` }{Query: query}","handlingStrategy":"validation","validationCode":"payload := struct{ Query string `json:\"query\"` }{Query: query}\nif b, err := json.Marshal(payload); err != nil || len(b) == 0 {\n    return errors.New(\"traversaal request payload not serializable\")\n}","typeGuard":null,"tryCatchPattern":"result, err := traversaalSearcher.Handle(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"failed to marshal request body\") {\n    return \"\", fmt.Errorf(\"code bug: non-serializable payload: %w\", err)\n}","preventionTips":["Keep request structs limited to JSON-serializable types","Add unit tests marshaling every searcher request payload","Avoid custom MarshalJSON on simple request types"],"tags":["go","json","traversaal","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}