sipeed/picoclaw · error
read response: %w
Error message
read response: %w
What it means
The request succeeded (200) but reading the full response body failed mid-stream while io.ReadAll drained it. The connection dropped after headers arrived, and the transport-level cause is wrapped.
Source
Thrown at cmd/picoclaw/internal/model/online.go:57
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, readErr := io.ReadAll(io.LimitReader(resp.Body, 512))
if readErr != nil {
return nil, fmt.Errorf("read error response: %w", readErr)
}
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read response: %w", err)
}
// {"data": [...]} envelope. Distinguish "envelope shape with empty list"
// from "object without a data key" via Data being non-nil after unmarshal:
// json.Unmarshal sets Data to []modelEntry{} for `{"data":[]}` but leaves
// it as nil when "data" is absent or null.
var envelope modelsAPIResponse
if err := json.Unmarshal(body, &envelope); err == nil && envelope.Data != nil {
return envelope.Data, nil
}
// Bare-array shape, including `[]`.
var arr []modelEntry
if err := json.Unmarshal(body, &arr); err == nil {
return arr, nil
}
preview := bodyView on GitHub (pinned to 49183d7e8d)
Solutions
- Retry — most mid-body drops are transient.
- If reproducible, fetch the URL with curl and observe where the body truncates.
- For huge catalogs, run from a nearer network or use a provider endpoint with pagination/filtering.
Defensive patterns
Strategy: retry
Try / catch
body, err := io.ReadAll(resp.Body)
if err != nil {
var nerr net.Error
if errors.As(err, &nerr) && nerr.Timeout() {
return retryWithBackoff() // body read exceeded client timeout
}
return fmt.Errorf("read response: %w", err)
} Prevention
- Retry once on mid-body failures — they are overwhelmingly transient.
- For large catalogs, prefer providers/endpoints with pagination to keep bodies small.
When it happens
Trigger: The server or a proxy closes the connection partway through the /models JSON body — RST mid-body, proxy idle cutoff, or the 15s client timeout expiring during a large body read at online.go:57.
Common situations: Very large model catalogs over slow links, flaky mobile/VPN networks, or intermediaries that truncate long responses.
Related errors
- read error response: %w
- failed to get WeCom QR code: %w
- unexpected status %s
- request failed: %w
- reading usage response: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/6e0fc54292327e12.
Report an issue: GitHub.