{"record":{"id":"ce6252b90ad0d06c","repo":"sipeed/picoclaw","slug":"failed-to-marshal-request-w","errorCode":null,"errorMessage":"failed to marshal request: %w","messagePattern":"failed to marshal request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/audio/tts/openai_tts.go","lineNumber":181,"sourceCode":"}\n\nfunc (t *OpenAITTSProvider) doSpeechRequest(\n\tctx context.Context,\n\ttext string,\n\tresponseFormat string,\n) (io.ReadCloser, error) {\n\treqBody := map[string]any{\n\t\t\"model\": t.model,\n\t\t\"input\": text,\n\t\t\"voice\": t.voice,\n\t}\n\tif responseFormat != \"\" {\n\t\treqBody[\"response_format\"] = responseFormat\n\t}\n\n\tjsonData, 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\", t.apiBase, bytes.NewReader(jsonData))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"Authorization\", \"Bearer \"+t.apiKey)\n\n\tresp, err := t.httpClient.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to send request: %w\", err)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tdefer resp.Body.Close()\n\t\tbody, readErr := io.ReadAll(resp.Body)","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/audio/tts/openai_tts.go#L163-L199","documentation":"Returned by OpenAITTSProvider.doSpeechRequest when json.Marshal of the {model, input, voice[, response_format]} map fails. All values are plain strings sourced from configuration, and strings always marshal, so this is unreachable in the shipped code — only a fork placing a non-marshalable type (chan, func) into reqBody could trigger it.","triggerScenarios":"Modified code putting func/chan/complex values into reqBody; no configuration input can cause it.","commonSituations":"Custom forks of the provider only.","solutions":["Keep reqBody values as strings","In custom code, convert non-serializable values (e.g. time.Duration.String()) before adding them to the map"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil {\n    // unreachable with string-only request fields: fail fast and report as a code defect\n}","preventionTips":["Keep request body values as plain strings","In forks, never put func/chan/time.Duration values into reqBody without converting them"],"tags":["json","tts","openai","internal"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}