{"record":{"id":"6ab5275b065fea57","repo":"sipeed/picoclaw","slug":"failed-to-send-request-w-6ab527","errorCode":null,"errorMessage":"failed to send request: %w","messagePattern":"failed to send request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/audio/tts/mimo_tts.go","lineNumber":124,"sourceCode":"\t\t\"stream\": false,\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(\"Api-Key\", 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\tdefer resp.Body.Close()\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read response: %w\", err)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"API error (status %d): %s\", resp.StatusCode, string(body))\n\t}\n\n\tvar payload struct {\n\t\tChoices []struct {\n\t\t\tMessage struct {\n\t\t\t\tAudio struct {\n\t\t\t\t\tData string `json:\"data\"`\n\t\t\t\t} `json:\"audio\"`","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/audio/tts/mimo_tts.go#L106-L142","documentation":"Returned by MimoTTSProvider.Synthesize when httpClient.Do fails before any response is received. The error is a *url.Error wrapping DNS failure, connection refused, TLS handshake problems, the fixed 60s client timeout, proxy failures, or context cancellation. Nothing about the request payload is at fault.","triggerScenarios":"api.xiaomimimo.com unreachable (DNS/firewall); proxyURL passed to NewMimoTTSProvider unparseable (it is silently dropped with a warning); client.Timeout of 60s exceeded for long texts; the caller's context canceled mid-request.","commonSituations":"Air-gapped or firewalled deployments; corporate proxy requirements; very long synthesis inputs exceeding the fixed timeout; intermittent connectivity.","solutions":["Verify reachability: curl -sS https://api.xiaomimimo.com/v1/chat/completions","If a proxy is required, pass a parseable proxyURL — invalid ones are dropped with only a log warning","Retry with exponential backoff; transient transport errors are the norm","For long texts, split the input or build the provider with a longer client timeout"],"exampleFix":"// before\nstream, err := mimo.Synthesize(ctx, longText)\n// after (retry transient transport errors)\nvar stream io.ReadCloser\nerr := retryN(3, time.Second, func() error {\n    var e error\n    stream, e = mimo.Synthesize(ctx, longText)\n    var ue *url.Error\n    if errors.As(e, &ue) && !errors.Is(e, context.Canceled) {\n        return e // retry\n    }\n    return nil\n})","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(`tcp`, `api.xiaomimimo.com:443`, 3*time.Second)\nif err != nil {\n    return fmt.Errorf(`mimo tts endpoint unreachable: %w`, err)\n}\n_ = conn.Close()","typeGuard":"func isTransientTransport(err error) bool {\n    var ue *url.Error\n    return errors.As(err, &ue) && !errors.Is(err, context.Canceled)\n}","tryCatchPattern":"var stream io.ReadCloser\nerr := retryN(3, time.Second, func() error {\n    var e error\n    stream, e = provider.Synthesize(ctx, text)\n    if e != nil && isTransientTransport(e) {\n        return e\n    }\n    return nil // stop on non-transport errors\n})","preventionTips":["Verify egress to api.xiaomimimo.com:443 before enabling mimo TTS","Pass a valid proxyURL when a proxy is required — unparseable ones are dropped with a warning","Split very long texts; the client timeout is fixed at 60s"],"tags":["network","http","dns","timeout","tts","mimo"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}