chenhg5/cc-connect · error

range chunk retries exhausted: %w

Error message

range chunk retries exhausted: %w

What it means

resourceRangeChunk retries a chunk only up to maxTransientRetries times for transient errors (network hiccups, 5xx). When all attempts fail, it returns 'range chunk retries exhausted' wrapping the last observed error (or a generic message if none was recorded). This signals sustained failure of one range fetch, not a single blip.

Source

Thrown at platform/feishu/resource_download.go:381

		if resp.StatusCode >= 500 && resp.StatusCode < 600 && attempt < maxTransientRetries {
			lastErr = fmt.Errorf("range status %d body=%q", resp.StatusCode, strings.TrimSpace(string(body)))
			continue
		}

		if resp.StatusCode >= 200 && resp.StatusCode < 300 && end-start+1 == int64(len(body)) {
			// Server ignored Range and returned a 200 with exactly the bytes
			// we wanted — fine for the last chunk of a file, slightly off for
			// non-tail chunks. Caller decides; we return what we got.
			return body, nil
		}

		return nil, fmt.Errorf("range request status=%d body=%q", resp.StatusCode, strings.TrimSpace(string(body)))
	}

	if lastErr == nil {
		lastErr = errors.New("range chunk retries exhausted")
	}
	return nil, fmt.Errorf("range chunk retries exhausted: %w", lastErr)
}

// defaultResourceChunkSize returns the chunk size used when a Platform is
// constructed without going through newPlatform (tests, manual fixtures).
// Matches the production default of 8 MiB.
func defaultResourceChunkSize() int64 { return 8 * 1024 * 1024 }

// fetchResourceTokenOrDefault returns the bearer token used for resource
// downloads. Tests can inject a stub via Platform.fetchResourceToken;
// production callers fall through to fetchFreshTenantAccessToken which uses
// the lark SDK to mint a fresh tenant token on demand.
func (p *Platform) fetchResourceTokenOrDefault(ctx context.Context) (string, error) {
	if p.fetchResourceToken != nil {
		return p.fetchResourceToken(ctx)
	}
	return p.fetchFreshTenantAccessToken(ctx)
}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Wait and retry the download after the transient condition clears (the wrapped lastErr tells you what kept failing)
  2. Check network connectivity/proxy stability and Feishu service health
  3. Increase maxTransientRetries and/or add backoff between attempts for flaky networks
  4. Split the file into smaller chunks so transient outages cost less progress

Example fix

// before
go download(fileToken)
// after: retry whole download with backoff
for i := 0; i < 3; i++ {
    err := download(fileToken)
    if err == nil || !strings.Contains(err.Error(), "retries exhausted") { break }
    time.Sleep(time.Duration(1<<i) * time.Second)
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight reachability check before chunked downloads
if err := pingFeishuAPI(3*time.Second); err != nil {
    return fmt.Errorf("skip download, API unreachable: %w", err)
}

Try / catch

if err := downloadResource(fileToken); err != nil && strings.Contains(err.Error(), "retries exhausted") {
    // sustained failure: exponential backoff, then alert
    backoffRetry(func() error { return downloadResource(fileToken) }, 5)
}

Prevention

When it happens

Trigger: resourceFetchRemainingChunks -> resourceRangeChunk: every attempt in the retry loop fails — repeated transient io errors or repeated 5xx responses — until attempt >= maxTransientRetries, then this wrapped error is returned.

Common situations: Prolonged network outage; Feishu API brownout during a large download; aggressive proxy dropping Range requests; host DNS/resolution issues persisting across retries.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/e264f8925fabd0cc. Report an issue: GitHub.