{"record":{"id":"3fcd2027d9b1ea02","repo":"chenhg5/cc-connect","slug":"first-chunk-206-without-parseable-content-range","errorCode":null,"errorMessage":"first-chunk: 206 without parseable Content-Range %q","messagePattern":"first-chunk: 206 without parseable Content-Range %q","errorType":"http","errorClass":null,"httpStatus":206,"severity":"error","filePath":"platform/feishu/resource_download.go","lineNumber":159,"sourceCode":"\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, p.resourceURL(messageID, fileKey, resType), nil)\n\tif err != nil {\n\t\treturn nil, 0, fmt.Errorf(\"build first-chunk request: %w\", err)\n\t}\n\treq.Header.Set(\"Authorization\", \"Bearer \"+token)\n\treq.Header.Set(\"Range\", \"bytes=0-0\")\n\n\tresp, err := p.resourceDownloadHTTP.Do(req)\n\tif err != nil {\n\t\treturn nil, 0, fmt.Errorf(\"first-chunk request: %w\", err)\n\t}\n\tdefer func() { _, _ = io.Copy(io.Discard, resp.Body); _ = resp.Body.Close() }()\n\n\tswitch resp.StatusCode {\n\tcase http.StatusPartialContent:\n\t\tcr := resp.Header.Get(\"Content-Range\")\n\t\ttotal, ok := parseContentRangeTotal(cr)\n\t\tif !ok {\n\t\t\treturn nil, 0, fmt.Errorf(\"first-chunk: 206 without parseable Content-Range %q\", cr)\n\t\t}\n\t\tbody, err := io.ReadAll(io.LimitReader(resp.Body, 1))\n\t\tif err != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"read first-chunk body: %w\", err)\n\t\t}\n\t\treturn body, total, nil\n\n\tcase http.StatusOK:\n\t\t// Server ignored Range and sent the full body. We deliberately\n\t\t// honour it and skip the chunked loop — this matches pre-#1741\n\t\t// behaviour for files small enough that Feishu doesn't truncate.\n\t\tbody, err := io.ReadAll(io.LimitReader(resp.Body, p.resourceMaxBytes+1))\n\t\tif err != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"read full body: %w\", err)\n\t\t}\n\t\tif int64(len(body)) > p.resourceMaxBytes {\n\t\t\treturn nil, 0, fmt.Errorf(\"resource too large: body exceeds cap %d\", p.resourceMaxBytes)\n\t\t}","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/resource_download.go#L141-L177","documentation":"Thrown when the Feishu server responds 206 Partial Content but the Content-Range header cannot be parsed by parseContentRangeTotal — missing header, malformed, or 'bytes 0-0/*' with an unknown total. The chunked downloader needs the total size to plan and verify the chunk loop, so an unparseable header is a protocol violation it refuses to guess at. Like all first-chunk failures, this triggers the plain-GET fallback.","triggerScenarios":"resp.StatusCode == 206 while resp.Header.Get(\"Content-Range\") is empty, lacks a '/' segment, ends with '/*', or has a non-numeric/invalid total (parseContentRangeTotal returns false).","commonSituations":"An intermediate proxy or non-Feishu-compatible server (e.g. in tests or custom-domain gateways) returning 206 without proper Content-Range; broken reverse-proxy caching layers mangling headers.","solutions":["Rely on the automatic resourceSingleGet fallback — verify it succeeds in logs ('first-chunk fetch failed; trying plain GET')","Inspect the reported Content-Range value in the error to identify the intermediary mangling headers","Bypass or fix the proxy/CDN that strips or rewrites Content-Range"],"exampleFix":"null","handlingStrategy":"fallback","validationCode":"null","typeGuard":"null","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"parseable Content-Range\") {\n    // library already falls back to plain GET; surface a degraded-mode log\n    slog.Warn(\"range unsupported by upstream; single-GET path used\", \"err\", err)\n}","preventionTips":["Avoid proxies/CDNs in front of the Feishu API that rewrite or strip headers","Pin the configured domain to official Feishu/Lark endpoints","Keep unit-test HTTP stubs spec-compliant (206 must include Content-Range)","Alert on repeated occurrences — they indicate a broken intermediary, not bad input"],"tags":["go","feishu","http","range-request","protocol"],"backgroundTag":"unexpected-response-shape","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"}