{"record":{"id":"ec1a5c79ef5d6ad5","repo":"larksuite/cli","slug":"unknown-total-size-in-content-range-q","errorCode":null,"errorMessage":"unknown total size in content-range: %q","messagePattern":"unknown total size in content-range: %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extension/download/download.go","lineNumber":686,"sourceCode":"func (cr contentRange) length() int64 {\n\treturn cr.end - cr.start + 1\n}\n\nfunc parseContentRange(header string) (contentRange, error) {\n\theader = strings.TrimSpace(header)\n\tif header == \"\" {\n\t\treturn contentRange{}, fmt.Errorf(\"content-range is empty\")\n\t}\n\tunit, spec, found := strings.Cut(header, \" \")\n\tif !found || !strings.EqualFold(unit, \"bytes\") {\n\t\treturn contentRange{}, fmt.Errorf(\"unsupported content-range: %q\", header)\n\t}\n\tparts := strings.SplitN(strings.TrimSpace(spec), \"/\", 2)\n\tif len(parts) != 2 || parts[0] == \"\" || parts[1] == \"\" || parts[0] == \"*\" {\n\t\treturn contentRange{}, fmt.Errorf(\"unsupported content-range: %q\", header)\n\t}\n\tif parts[1] == \"*\" {\n\t\treturn contentRange{}, fmt.Errorf(\"unknown total size in content-range: %q\", header)\n\t}\n\tbounds := strings.SplitN(parts[0], \"-\", 2)\n\tif len(bounds) != 2 || bounds[0] == \"\" || bounds[1] == \"\" {\n\t\treturn contentRange{}, fmt.Errorf(\"unsupported content-range: %q\", header)\n\t}\n\tstart, err := strconv.ParseInt(bounds[0], 10, 64)\n\tif err != nil {\n\t\treturn contentRange{}, fmt.Errorf(\"parse range start: %w\", err)\n\t}\n\tend, err := strconv.ParseInt(bounds[1], 10, 64)\n\tif err != nil {\n\t\treturn contentRange{}, fmt.Errorf(\"parse range end: %w\", err)\n\t}\n\ttotal, err := strconv.ParseInt(parts[1], 10, 64)\n\tif err != nil {\n\t\treturn contentRange{}, fmt.Errorf(\"parse total size: %w\", err)\n\t}\n\tif total <= 0 {","sourceCodeStart":668,"sourceCodeEnd":704,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/extension/download/download.go#L668-L704","documentation":"The Content-Range header's total-size field was '*', meaning the server does not know (or will not disclose) the full resource length. Partial-download logic needs the total size to compute offsets and verify completeness, so it refuses to continue.","triggerScenarios":"openPartial or openNext received 'bytes 0-99/*' from the server.","commonSituations":"Dynamic or chunked-encoding responses where the server cannot compute total length; some streaming gateways emit '*' totals; misconfigured storage proxies.","solutions":["Configure the storage/gateway to return the actual total size in Content-Range.","Ensure the object has a known Content-Length on the server side.","Download the whole resource in one request instead of using the partial/resumable path.","Check whether the URL points at a streaming endpoint rather than a static object."],"exampleFix":"// before\n// Content-Range: bytes 0-99/*\n// after\n// Content-Range: bytes 0-99/5000","handlingStrategy":"fallback","validationCode":"func knownTotal(h string) bool {\n\t_, spec, _ := strings.Cut(h, \" \")\n\t_, total, _ := strings.Cut(spec, \"/\")\n\treturn total != \"*\"\n}","typeGuard":null,"tryCatchPattern":"cr, err := parseContentRange(header)\nif err != nil {\n\t// unknown total: switch to streaming full-body download\n\treturn downloadFull(ctx, url)\n}","preventionTips":["Configure storage/gateway to always report object size","Download static objects, not streaming endpoints, when resuming","Check Content-Length is present before issuing Range requests"],"tags":["http","content-range","download"],"backgroundTag":"invalid-content-range-header","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}