chenhg5/cc-connect · error
extract binary: %w
Error message
extract binary: %w
What it means
SelfUpdate (core/updater.go:166) wraps any failure to extract the cc-connect binary from the downloaded archive as `extract binary: %w`. For non-Windows the archive is parsed as tar.gz (extractBinaryFromTarGz), for Windows as zip (extractBinaryFromZip). The extractor fails if the data isn't a valid gzip/tar/zip stream, is truncated, or contains no regular file whose base name starts with `cc-connect`.
Source
Thrown at core/updater.go:166
data, lastErr = downloadFile(u)
if lastErr == nil {
break
}
slog.Debug("updater: download failed, trying next", "error", lastErr)
}
if lastErr != nil && data == nil {
return fmt.Errorf("download failed from all sources: %w", lastErr)
}
var binary []byte
var err error
if goos == "windows" {
binary, err = extractBinaryFromZip(data)
} else {
binary, err = extractBinaryFromTarGz(data)
}
if err != nil {
return fmt.Errorf("extract binary: %w", err)
}
return replaceBinary(binary)
}
func downloadFile(url string) ([]byte, error) {
client := &http.Client{
Timeout: 5 * time.Minute,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) > 10 {
return fmt.Errorf("too many redirects")
}
return nil
},
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, errView on GitHub (pinned to 4000b2338a)
Solutions
- Inspect the wrapped cause: gzip/zip header errors mean the payload isn't an archive (likely HTML from a proxy) — download the URL manually with curl and `file` it to confirm.
- Verify the archive actually contains a binary whose base name starts with `cc-connect` (`tar tzf` / `unzip -l`); if the release renamed it, fix the asset naming or the prefix check.
- Re-run the upgrade; transient truncation usually resolves on retry, or switch sources with preferGitee.
- Check disk space / memory — very large truncated bodies can also fail decode.
- If a proxy returns 200 HTML pages, bypass the proxy for release download hosts.
Example fix
// before: silently accepts any 200 body, even HTML
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP %d for %s", resp.StatusCode, url)
}
return io.ReadAll(resp.Body)
// after: sanity-check the payload looks like gzip before returning
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP %d for %s", resp.StatusCode, url)
}
data, err := io.ReadAll(resp.Body)
if err == nil && len(data) > 2 && data[0] != 0x1f && data[1] != 0x8b && runtime.GOOS != "windows" {
return nil, fmt.Errorf("downloaded payload for %s is not a gzip archive", url)
}
return data, err Defensive patterns
Strategy: validation
Validate before calling
func looksLikeArchive(data []byte, windows bool) error {
if len(data) < 4 {
return errors.New("archive too small")
}
if windows {
if data[0] != 'P' || data[1] != 'K' {
return errors.New("not a zip archive (proxy HTML page?)")
}
return nil
}
if data[0] != 0x1f || data[1] != 0x8b {
return errors.New("not a gzip archive (proxy HTML page?)")
}
return nil
} Try / catch
if err := core.SelfUpdate(tag, preferGitee); err != nil {
if strings.Contains(err.Error(), "extract binary") {
slog.Error("downloaded archive invalid — no install attempted", "err", err)
// check for proxy-intercepted payload or renamed inner binary, then retry
}
return err
} Prevention
- Verify with `file`/magic bytes that the downloaded asset is really tar.gz or zip before extraction.
- Ensure releases keep a regular file whose base name starts with `cc-connect` in the archive.
- Bypass proxies that return 200 HTML error/captcha pages for release download hosts.
- Retry truncated downloads; verify content-length against the asset size when possible.
- Don't mix .zip and .tar.gz assets across platforms — keep the GOOS-based extension logic.
When it happens
Trigger: downloadFile succeeded but returned a non-archive payload: a 200 HTML error/captcha page from an intercepting proxy, a truncated download, a corrupt/renamed release asset, or an archive that lacks a file matching the `cc-connect` name prefix (extractBinaryFromTarGz:223 / Zip:242 return 'cc-connect binary not found...'). Triggered during SelfUpdate for the current GOOS.
Common situations: Corporate proxies or captive portals returning HTML with status 200; partially downloaded archives over flaky links; release packaging changes that rename the inner binary (e.g. to `agent` or a versioned name); CDN serving an error page; mixing up .zip/.tar.gz for the wrong OS.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- gzip: %w
- tar: %w
- cc-connect binary not found in archive
- cc-connect binary not found in zip archive
- extract: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/9dad3c4be2f8c249.
Report an issue: GitHub.