{"record":{"id":"00693ebf4a7d0934","repo":"chenhg5/cc-connect","slug":"build-range-request-w","errorCode":null,"errorMessage":"build range request: %w","messagePattern":"build range request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/resource_download.go","lineNumber":319,"sourceCode":"\tvar lastErr error\n\tdelay := transientRetryInitial\n\tfor attempt := 0; attempt <= maxTransientRetries; attempt++ {\n\t\tif attempt > 0 {\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn nil, ctx.Err()\n\t\t\tcase <-time.After(delay):\n\t\t\t}\n\t\t\tdelay *= 2\n\t\t\tif delay > transientRetryMaxDelay {\n\t\t\t\tdelay = transientRetryMaxDelay\n\t\t\t}\n\t\t}\n\n\t\treq, err := http.NewRequestWithContext(ctx, http.MethodGet,\n\t\t\tp.resourceURL(messageID, fileKey, resType), nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"build range request: %w\", err)\n\t\t}\n\t\treq.Header.Set(\"Authorization\", \"Bearer \"+token)\n\t\treq.Header.Set(\"Range\", fmt.Sprintf(\"bytes=%d-%d\", start, end))\n\n\t\tresp, err := p.resourceDownloadHTTP.Do(req)\n\t\tif err != nil {\n\t\t\tif isTransientError(err) && attempt < maxTransientRetries {\n\t\t\t\tlastErr = err\n\t\t\t\tslog.Debug(p.tag()+\": transient range chunk error; retrying\",\n\t\t\t\t\t\"attempt\", attempt, \"error\", err, \"start\", start, \"end\", end)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"range request: %w\", err)\n\t\t}\n\n\t\tif resp.StatusCode == http.StatusPartialContent {\n\t\t\tcr := resp.Header.Get(\"Content-Range\")\n\t\t\tif cr != \"\" {","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/resource_download.go#L301-L337","documentation":"resourceRangeChunk failed to construct its HTTP Range GET request via http.NewRequestWithContext and wraps the cause as \"build range request\". This mirrors the single-GET build failure but on the per-chunk path used for large downloads.","triggerScenarios":"p.resourceURL(messageID, fileKey, resType) yields an unparseable URL when fetching a chunk — empty/invalid message_id or file_key, unescaped characters in the file key, or a malformed configured base URL — during a chunked download of a large resource.","commonSituations":"fileKey containing characters that break url.Parse (spaces, control chars, unencoded %-signs); message_id empty because the incoming message lacked it; base URL misconfigured behind a gateway.","solutions":["Check the wrapped cause (%w) — url.Parse errors pinpoint the offending URL segment","Validate messageID and fileKey (non-empty, URL-safe) before starting the chunked download","Fix p.resourceURL / base URL configuration if it produces invalid URLs","Since a per-chunk build failure repeats for every chunk, abort and fix inputs rather than retrying"],"exampleFix":"// before: use raw fileKey\nreq, err := http.NewRequestWithContext(ctx, http.MethodGet, p.resourceURL(messageID, fileKey, resType), nil)\n// after: reject invalid keys up front\nif fileKey == \"\" || strings.ContainsAny(fileKey, \" \\t\\r\\n%\") {\n    return nil, fmt.Errorf(\"feishu: invalid file_key %q\", fileKey)\n}","handlingStrategy":"validation","validationCode":"func validRangeInputs(msgID, fileKey string) error {\n    if msgID == \"\" { return fmt.Errorf(\"empty message_id\") }\n    if fileKey == \"\" { return fmt.Errorf(\"empty file_key\") }\n    return nil\n}\n// call before starting the chunked download\nif err := validRangeInputs(msgID, fileKey); err != nil { return err }","typeGuard":null,"tryCatchPattern":"data, err := p.resourceDownloadStream(ctx, token, msgID, fileKey, resType)\nif err != nil {\n    if strings.Contains(err.Error(), \"build range request\") {\n        // deterministic failure: do not retry, fix inputs\n        return nil, fmt.Errorf(\"bad resource identifiers: %w\", err)\n    }\n    return err\n}","preventionTips":["Reject empty or non-URL-safe message_id/file_key before chunked downloads","Fail fast: a per-chunk URL build error repeats for every chunk, so don't retry","Unit-test resourceURL with representative file keys"],"tags":["http","url","chunked-download","feishu"],"backgroundTag":"invalid-url","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"}