AlistGo/alist · error
failed to read response body: %v
Error message
failed to read response body: %v
What it means
io.ReadAll on the response body of POST /upload/resumable.php failed while draining the upload unit acknowledgement. This is a transport-level failure mid-body: the connection dropped after headers were sent, or the body was cut off. The request itself may or may not have been processed server-side, which matters for resumable-upload correctness.
Source
Thrown at drivers/mediafire/util.go:425
req.ContentLength = int64(len(unitData))
/* fmt.Printf("Debug resumable upload request:\n")
fmt.Printf(" URL: %s\n", req.URL.String())
fmt.Printf(" Headers: %+v\n", req.Header)
fmt.Printf(" Unit ID: %d\n", unitID)
fmt.Printf(" Unit Size: %d\n", len(unitData))
fmt.Printf(" Upload Key: %s\n", uploadKey)
fmt.Printf(" Action Token: %s\n", actionToken) */
res, err := base.HttpClient.Do(req)
if err != nil {
return "", err
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %v", err)
}
//fmt.Printf("MediaFire resumable upload response (status %d): %s\n", res.StatusCode, string(body))
var uploadResp struct {
Response struct {
Doupload struct {
Key string `json:"key"`
} `json:"doupload"`
Result string `json:"result"`
} `json:"response"`
}
if err := json.Unmarshal(body, &uploadResp); err != nil {
return "", fmt.Errorf("failed to parse response: %v", err)
}
if res.StatusCode != 200 {View on GitHub (pinned to 843d9dc814)
Solutions
- Retry the unit upload — the protocol is resumable and bitmap-tracked, so re-sending a unit is safe
- Increase the shared HTTP client's timeout and TLS handshake timeout for large unit sizes
- If consistently reproducible, capture whether a proxy sits between client and api.mediafire.com and relax its limits
- Verify the upload key is still valid before retrying; if expired, re-run uploadCheck to get a new one
Example fix
// before
body, err := io.ReadAll(res.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %v", err)
}
// after
body, err := io.ReadAll(res.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body (unit %d, status %d): %w", unitID, res.StatusCode, err)
} Defensive patterns
Strategy: retry
Validate before calling
// Ensure client timeouts accommodate unit-sized transfers
if base.HttpClient.Timeout < time.Duration(unitSize)*time.Millisecond {
// use a per-request context deadline sized to the unit instead
ctx, cancel := context.WithTimeout(ctx, 10*time.Minute)
defer cancel()
} Try / catch
// Safe retry: resumable protocol tolerates re-sent units
err := d.resumableUpload(...)
for attempt := 0; attempt < 3 && isTransient(err); attempt++ {
time.Sleep(time.Duration(attempt+1) * time.Second)
err = d.resumableUpload(...)
} Prevention
- Size client timeouts to unit size and network speed
- Send units sequentially or cap concurrency to avoid proxy resets
- Verify upload key validity before retrying after long delays
When it happens
Trigger: Connection reset/timeout while MediaFire streams the (often large) JSON acknowledgement; proxy or reverse proxy truncating the response; TLS renegotiation mid-body; very slow networks where the client read deadline expires.
Common situations: Mobile or unstable networks uploading large units; corporate proxies with body-size or idle limits; MediaFire server-side connection churn during peak load; misconfigured HTTP client timeouts shorter than body transfer time.
Related errors
- upload request failed: %w
- expected *os.File, got %T
- failed to get action token: %w
- MediaFire upload check failed: %s
- failed to parse response: %v
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/6d57ac103161d013.
Report an issue: GitHub.