{"record":{"id":"00b9d6892d042de4","repo":"chenhg5/cc-connect","slug":"qwen-tts-marshal-request-w","errorCode":null,"errorMessage":"qwen tts: marshal request: %w","messagePattern":"qwen tts: marshal request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tts.go","lineNumber":136,"sourceCode":"func (q *QwenTTS) Synthesize(ctx context.Context, text string, opts TTSSynthesisOpts) ([]byte, string, error) {\n\tvoice := opts.Voice\n\tif voice == \"\" {\n\t\tvoice = \"Cherry\"\n\t}\n\treqBody := map[string]any{\n\t\t\"model\": q.Model,\n\t}\n\tinput := map[string]any{\n\t\t\"text\":  text,\n\t\t\"voice\": voice,\n\t}\n\tif opts.LanguageType != \"\" {\n\t\tinput[\"language_type\"] = opts.LanguageType\n\t}\n\treqBody[\"input\"] = input\n\tjsonData, err := json.Marshal(reqBody)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"qwen tts: marshal request: %w\", err)\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, q.BaseURL, bytes.NewReader(jsonData))\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"qwen tts: create request: %w\", err)\n\t}\n\treq.Header.Set(\"Authorization\", \"Bearer \"+q.APIKey)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := q.Client.Do(req)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"qwen tts: request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"qwen tts: read response: %w\", err)","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/tts.go#L118-L154","documentation":"QwenTTS.Synthesize builds the JSON request body (model, input text, optional language_type) with json.Marshal. If marshaling fails it wraps the error as 'qwen tts: marshal request'. This is nearly impossible with the fixed struct shape and typically indicates a programming-level serialization problem.","triggerScenarios":"json.Marshal(reqBody) returns an error — for a map[string]any/struct of plain strings this effectively only happens if an unsupported value type (e.g. a channel, func, or cyclic value) was injected into reqBody.","commonSituations":"Custom code that mutates the request map with non-JSON-serializable values before Synthesize is called; generics/refactor code placing a wrong-typed value into the options.","solutions":["Inspect the wrapped error and the values placed into the request body; remove any non-JSON-serializable values.","Ensure opts fields (Text, LanguageType) are plain strings.","This is an internal bug if you only pass normal string options — file/debug the code constructing reqBody."],"exampleFix":"// before\nreqBody[\"input\"] = someRuntimeValue // may be unserializable\n// after\nreqBody[\"input\"] = fmt.Sprintf(\"%v\", someRuntimeValue)","handlingStrategy":"try-catch","validationCode":"if opts.Text == \"\" || opts.LanguageType == \"\" && false {\n    // only plain strings allowed in request body\n}\n// ensure any custom values injected into the request are JSON-encodable\nif err := json.Marshal(reqBody); err != nil { /* fix value types before calling Synthesize */ }","typeGuard":null,"tryCatchPattern":"audio, url, err := q.Synthesize(ctx, text, opts)\nif err != nil {\n    var se *fmt.wrapError\n    if errors.As(err, &se) && strings.Contains(err.Error(), \"marshal request\") {\n        slog.Error(\"qwen tts request construction bug\", \"err\", err)\n    }\n    return err\n}","preventionTips":["Keep request body values restricted to JSON-safe types (string, number, bool).","Never insert runtime arbitrary values into the request map without conversion.","Cover Synthesize with a unit test asserting request JSON shape."],"tags":["tts","qwen","json","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}