chenhg5/cc-connect · warning

unexpected redirect: %s

Error message

unexpected redirect: %s

What it means

fetchLatestStableRelease parses the redirect Location URL by splitting on "/tag/" and expects exactly two parts. This error means the Location header was present but its format didn't match the expected https://github.com/<owner>/<repo>/releases/tag/<tag> shape, so the tag cannot be extracted.

Source

Thrown at cmd/cc-connect/update.go:282

	noRedirect := &http.Client{
		Timeout: 15 * time.Second,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	resp2, err := noRedirect.Get(latestURL)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp2.Body.Close()

	loc := resp2.Header.Get("Location")
	if loc == "" {
		return nil, fmt.Errorf("no release found")
	}
	parts := strings.Split(loc, "/tag/")
	if len(parts) != 2 {
		return nil, fmt.Errorf("unexpected redirect: %s", loc)
	}
	return &githubRelease{TagName: parts[1], HTMLURL: loc}, nil
}

func binaryAssetName(tag string) string {
	goos := runtime.GOOS
	goarch := runtime.GOARCH
	name := fmt.Sprintf("cc-connect-%s-%s-%s", tag, goos, goarch)
	if goos == "windows" {
		name += ".exe"
	}
	return name
}

func archiveAssetName(tag string) string {
	goos := runtime.GOOS
	goarch := runtime.GOARCH
	base := fmt.Sprintf("cc-connect-%s-%s-%s", tag, goos, goarch)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the actual Location value embedded in the message to see what GitHub returned
  2. Bypass any SSO/proxy that rewrites redirects to github.com
  3. Parse the tag with net/url path parsing instead of naive string splitting to tolerate URL variations
  4. Fall back to the JSON /releases endpoint, whose tag_name field is stable

Example fix

// before
parts := strings.Split(loc, "/tag/")
if len(parts) != 2 {
    return nil, fmt.Errorf("unexpected redirect: %s", loc)
}
// after
u, err := url.Parse(loc)
if err != nil {
    return nil, fmt.Errorf("unexpected redirect: %s", loc)
}
segs := strings.Split(strings.TrimRight(u.Path, "/"), "/")
if len(segs) < 2 || segs[len(segs)-2] != "tag" {
    return nil, fmt.Errorf("unexpected redirect: %s", loc)
}
tag := segs[len(segs)-1]
Defensive patterns

Strategy: type-guard

Validate before calling

// sanity-check the Location URL shape before trusting it:
loc := resp.Header.Get("Location")
u, err := url.Parse(loc)
if err != nil || u.Host != "github.com" || !strings.Contains(u.Path, "/releases/tag/") {
    return errors.New("redirect does not look like a release URL: " + loc)
}

Type guard

// Go: narrowing helper for a valid release-redirect URL
func isReleaseRedirect(loc string) (tag string, ok bool) {
    u, err := url.Parse(loc)
    if err != nil || u.Host != "github.com" { return "", false }
    parts := strings.Split(strings.Trim(u.Path, "/"), "/")
    if len(parts) < 5 || parts[len(parts)-2] != "tag" { return "", false }
    return parts[len(parts)-1], true
}

Try / catch

// Go: validate the parsed tag before proceeding
tag, ok := isReleaseRedirect(loc)
if !ok {
    return nil, fmt.Errorf("unexpected redirect: %s", loc) // log loc verbatim for triage
}

Prevention

When it happens

Trigger: strings.Split(loc, "/tag/") returns != 2 parts: Location points somewhere unexpected — a login/SSO redirect, an error page, a proxy URL, or a changed releases URL layout.

Common situations: An SSO/identity provider redirect intercepting the request; a misconfigured internal proxy rewriting Location; repo moved/renamed causing a redirect chain to a different URL format; future GitHub URL scheme change.

Related errors


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