sipeed/picoclaw · error
failed to read response: %w
Error message
failed to read response: %w
What it means
Returned by MimoTTSProvider.Synthesize when io.ReadAll fails while draining resp.Body. The request already succeeded at the transport level; the failure is a mid-body connection reset, the server closing early, context cancellation during the read, or an enormous base64 response exhausting memory.
Source
Thrown at pkg/audio/tts/mimo_tts.go:130
}
req, err := http.NewRequestWithContext(ctx, "POST", t.apiBase, bytes.NewReader(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Api-Key", t.apiKey)
resp, err := t.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to send request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(body))
}
var payload struct {
Choices []struct {
Message struct {
Audio struct {
Data string `json:"data"`
} `json:"audio"`
} `json:"message"`
} `json:"choices"`
}
err = json.Unmarshal(body, &payload)
if err != nil {View on GitHub (pinned to 49183d7e8d)
Solutions
- Retry once — partial reads are usually transient
- Shorten the input text to reduce response size
- Verify proxy and read-idle timeouts on the network path
- Keep the context alive for the entire Synthesize call
Defensive patterns
Strategy: retry
Type guard
func isBodyReadFailure(err error) bool {
var ne net.Error
return errors.Is(err, io.ErrUnexpectedEOF) || errors.As(err, &ne)
} Try / catch
if err != nil && isBodyReadFailure(err) {
// response broke mid-read: safe to retry — the request body is rebuilt from bytes each attempt
} Prevention
- Keep the caller context alive until Synthesize returns
- Shorten inputs to shrink the base64 response body
- Check proxy idle/read timeouts on the network path
When it happens
Trigger: Connection dropped between response headers and the final chunk (proxy/idle timeouts); server closes keep-alive early; caller cancels ctx mid-read; multi-MB audio payload for very long text read in one shot.
Common situations: Flaky mobile networks; aggressive corporate proxies; long synthesis inputs producing large base64 bodies.
Related errors
- failed to send request: %w
- failed to write tts audio: %w
- failed to read response: %w
- API error (status %d): %s
- failed to decode response: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/2702015c35cdb785.
Report an issue: GitHub.