larksuite/cli · error

official skills index returned HTTP %d

Error message

official skills index returned HTTP %d

What it means

FetchSkillsIndex recorded on its result that the official skills index endpoint answered with a status outside 2xx; non-HTTPS redirects were already rejected earlier by the CheckRedirect hook, so this is a server-side index availability failure.

Source

Thrown at internal/selfupdate/updater.go:311

		return r
	}

	client := transport.NewHTTPClient(0)
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		if req.URL.Scheme != "https" {
			return fmt.Errorf("official skills index redirected to non-HTTPS URL: %s", req.URL.Redacted())
		}
		return nil
	}
	resp, err := client.Do(req)
	if err != nil {
		r.Err = err
		return r
	}
	defer resp.Body.Close()

	if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
		r.Err = fmt.Errorf("official skills index returned HTTP %d", resp.StatusCode)
		return r
	}

	limited := io.LimitReader(resp.Body, skillsIndexMaxBodySize+1)
	if _, err := io.Copy(&r.Stdout, limited); err != nil {
		r.Err = err
		return r
	}
	if r.Stdout.Len() > skillsIndexMaxBodySize {
		r.Stdout.Reset()
		r.Err = fmt.Errorf("official skills index exceeds %d bytes", skillsIndexMaxBodySize)
		return r
	}
	return r
}

func (u *Updater) ListGlobalSkills() *NpmResult {
	return u.runSkillsListGlobal()

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Read the HTTP status in the message: for 404 verify the skills-index URL/source is current, for 403/401 check access/auth to the mirror
  2. For 429 wait and retry later (respect rate limits) or reduce polling frequency
  3. For 5xx check the service status of the index host and retry after the outage
  4. Check proxy/VPN configuration that may be intercepting requests to the index host

Example fix

// before
res := updater.FetchSkillsIndex(source)
if res.Err != nil { log.Fatal(res.Err) }
// after
res := updater.FetchSkillsIndex(source)
if res.Err != nil {
	var statusMsg string
	if _, err := fmt.Sscanf(res.Err.Error(), "official skills index returned HTTP %s", &statusMsg); err == nil && strings.HasPrefix(statusMsg, "5") {
		log.Printf("index host error, retrying later: %v", res.Err)
	} else {
		log.Fatal(res.Err)
	}
}
Defensive patterns

Strategy: retry

Validate before calling

resp, err := http.Head(indexURL)
if err == nil && (resp.StatusCode < 200 || resp.StatusCode >= 300) { /* endpoint unhealthy; fix URL/auth before FetchSkillsIndex */ }

Try / catch

res := updater.FetchSkillsIndex(source)
if res.Err != nil {
	if strings.Contains(res.Err.Error(), "returned HTTP 5") || strings.Contains(res.Err.Error(), "HTTP 429") {
		// transient: retry with backoff
	} else {
		return res.Err // 404/403: fix URL or access
	}
}

Prevention

When it happens

Trigger: Calling Updater.FetchSkillsIndex(source) when the skills-index endpoint responds with a non-2xx status — 404 for a bad/removed index path, 403 for blocked access, 429 rate limiting, or 5xx server errors.

Common situations: Index URL changed or versioned path removed (404); auth required by an internal mirror (401/403); rate limiting by the CDN (429); upstream outage (500/502/503); proxy returning an error page.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/f6cf2f6fd80f56f2. Report an issue: GitHub.