{"record":{"id":"634c6458e12b0522","repo":"chenhg5/cc-connect","slug":"range-status-d-body-q","errorCode":null,"errorMessage":"range status %d body=%q","messagePattern":"range status (.+?) body=%q","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/resource_download.go","lineNumber":364,"sourceCode":"\t\t\t\tif isTransientError(err) && attempt < maxTransientRetries {\n\t\t\t\t\tlastErr = err\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"read range body: %w\", err)\n\t\t\t}\n\t\t\tif int64(len(body)) != end-start+1 {\n\t\t\t\treturn nil, fmt.Errorf(\"range body length %d != requested %d\", len(body), end-start+1)\n\t\t\t}\n\t\t\treturn body, nil\n\t\t}\n\n\t\t// Non-206 response: capture a snippet for diagnostics, then either\n\t\t// retry (transient 5xx) or fail fast.\n\t\tbody, _ := io.ReadAll(io.LimitReader(resp.Body, 4*1024))\n\t\t_ = resp.Body.Close()\n\n\t\tif resp.StatusCode >= 500 && resp.StatusCode < 600 && attempt < maxTransientRetries {\n\t\t\tlastErr = fmt.Errorf(\"range status %d body=%q\", resp.StatusCode, strings.TrimSpace(string(body)))\n\t\t\tcontinue\n\t\t}\n\n\t\tif resp.StatusCode >= 200 && resp.StatusCode < 300 && end-start+1 == int64(len(body)) {\n\t\t\t// Server ignored Range and returned a 200 with exactly the bytes\n\t\t\t// we wanted — fine for the last chunk of a file, slightly off for\n\t\t\t// non-tail chunks. Caller decides; we return what we got.\n\t\t\treturn body, nil\n\t\t}\n\n\t\treturn nil, fmt.Errorf(\"range request status=%d body=%q\", resp.StatusCode, strings.TrimSpace(string(body)))\n\t}\n\n\tif lastErr == nil {\n\t\tlastErr = errors.New(\"range chunk retries exhausted\")\n\t}\n\treturn nil, fmt.Errorf(\"range chunk retries exhausted: %w\", lastErr)\n}","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/resource_download.go#L346-L382","documentation":"When a range request returns a non-206 status in the 5xx band, resourceRangeChunk records 'range status %d body=%q' as lastErr and retries; if retries are exhausted or the status is not retryable, this error is returned (wrapped by 'range chunk retries exhausted' when it was the retained lastErr). The body snippet (up to 4 KiB) is included for diagnostics.","triggerScenarios":"resourceFetchRemainingChunks -> resourceRangeChunk: the ranged GET returns 5xx (e.g. 500/502/503/504) more than maxTransientRetries times, or a non-retryable non-206 status reaches the final error path with this message as lastErr.","commonSituations":"Feishu API outage or maintenance window; rate limiting manifesting as 5xx; gateway/load-balancer errors on large Range requests; transient upstream failures during sustained chunked downloads.","solutions":["Retry the download later; 5xx are retried automatically up to maxTransientRetries, so exhaustion implies a sustained outage","Inspect the included body snippet for a Feishu error code or maintenance notice","Check Feishu service status page for ongoing incidents","Add exponential backoff around the whole download rather than tighter loops"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// check Feishu API health before bulk downloads\nresp, err := http.Get(\"https://open.feishu.cn/\")\nif err != nil || resp.StatusCode >= 500 { /* defer the download */ }","typeGuard":null,"tryCatchPattern":"if err := downloadResource(fileToken); err != nil && strings.Contains(err.Error(), \"range status 5\") {\n    // 5xx from Feishu: back off and retry later\n    time.Sleep(time.Minute)\n    return downloadResource(fileToken)\n}","preventionTips":["Schedule bulk downloads outside known maintenance windows","Subscribe to Feishu/Open Platform status notifications","Use exponential backoff around whole-download operations","Don't hammer retries when the body snippet indicates a service incident"],"tags":["http","server-error","retry","feishu"],"backgroundTag":"http-error-response","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}