AlistGo/alist · error
bad status: %s, body: %s
Error message
bad status: %s, body: %s
What it means
Thrown by HalalCloud's slice downloader when the HTTP GET to addr.DownloadAddress returns any status other than 200. The full response body is included, which often contains the CDN/storage node's own error text. This is a transport-level failure against the per-slice download URL, before any decrypt or CID verification happens.
Source
Thrown at drivers/halalcloud/util.go:240
if addr == nil {
return nil, errors.New("addr is nil")
}
client := http.Client{
Timeout: time.Duration(60 * time.Second), // Set timeout to 5 seconds
}
resp, err := client.Get(addr.DownloadAddress)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("bad status: %s, body: %s", resp.Status, body)
}
if addr.Encrypt > 0 {
cd := uint8(addr.Encrypt)
for idx := 0; idx < len(body); idx++ {
body[idx] = body[idx] ^ cd
}
}
if addr.StoreType != 10 {
sourceCid, err := cid.Decode(addr.Identity)
if err != nil {
return nil, err
}
checkCid, err := sourceCid.Prefix().Sum(body)
if err != nil {
return nil, errView on GitHub (pinned to 843d9dc814)
Solutions
- Read the body in the message — 403 signature-expired vs 429 vs 500 each imply different fixes.
- Re-request the download address (re-run the address/API call) to get a fresh signed URL, then retry the slice.
- Add exponential backoff retry around the slice fetch for 429/5xx.
- Reduce slice-parallelism if rate limited.
Example fix
// before
body, err := downloadSlice(client, addr)
if err != nil { return err }
// after: refresh the signed address on non-200 and retry once
body, err := downloadSlice(client, addr)
if err != nil && strings.Contains(err.Error(), "bad status") {
addr, aerr := refreshDownloadAddress(ctx, fileID)
if aerr != nil { return aerr }
body, err = downloadSlice(client, addr)
}
if err != nil { return err } Defensive patterns
Strategy: retry
Try / catch
body, err := fetchSlice(client, addr)
if err != nil && strings.Contains(err.Error(), "bad status") {
if isRetryableStatus(err) { // 429/5xx embedded in message
time.Sleep(backoff)
addr, _ = refreshAddress(ctx)
body, err = fetchSlice(client, addr)
}
}
if err != nil { return err } Prevention
- Treat download addresses as short-lived: fetch them right before each slice
- Retry with backoff on 429/5xx
- Limit slice fetch parallelism
When it happens
Trigger: Expired signed download URL (addresses are short-lived), storage node temporarily down (5xx), rate limiting (429), or the file being deleted between address issuance and fetch.
Common situations: Long-running downloads that outlive the URL signature TTL; retrying after a pause; CDN node maintenance; aggressive parallel slice fetching triggering 429s.
Related errors
- addr is nil
- open download file failed: %w
- http request failure,status: %d
- missing cookie or qrcode account
- bad status code {res.Status()}
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/614e13639f41d555.
Report an issue: GitHub.