github/copilot-sdk · error

failed to fetch legacy package-lock.json

Error message

failed to fetch legacy package-lock.json: %w

What it means

This error wraps the underlying transport error from http.Get when fetching the legacy package-lock.json from the repo at a given git ref. The bundler falls back to the legacy lockfile to resolve the @github/copilot CLI version; if the HTTP request itself fails (DNS, TLS, connection refused, timeout), this error is thrown so the caller (fetchCLIVersionFromRepo) sees a descriptive chain.

Solutions

  1. Check network connectivity from the machine running the bundler (curl the URL manually).
  2. Verify the gitRef passed in resolves to a real ref so the constructed URL is valid.
  3. Configure proxy environment variables (HTTPS_PROXY) if behind a corporate proxy.
  4. Retry later if GitHub is temporarily unreachable; the error chain shows the root cause.
  5. Bypass the fallback by ensuring the primary version source (package.json copilotCliVersion) succeeds.

Example fix

// before
resp, err := http.Get(url)
if err != nil {
	return "", fmt.Errorf("failed to fetch legacy package-lock.json: %w", err)
}
// after
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Get(url)
if err != nil {
	return "", fmt.Errorf("failed to fetch legacy package-lock.json at %s: %w", url, err)
}
Defensive patterns

Strategy: retry

Validate before calling

url := fmt.Sprintf(packageLockURLFmt, gitRef)
if _, err := net.LookupHost("github.com"); err != nil {
	return errors.New("network unreachable: cannot fetch legacy package-lock.json")
}

Try / catch

var v string
var err error
for i := 0; i < 3; i++ {
	v, err = fetchLegacyCLIVersionFromRepo(gitRef)
	if err == nil || !errors.Is(err, context.DeadlineExceeded) && !isNetErr(err) {
		break
	}
	time.Sleep(time.Duration(1<<i) * time.Second)
}

Prevention

When it happens

Trigger: http.Get on the packageLockURLFmt URL built from the gitRef fails at the transport level — DNS resolution failure, connection refused, TLS handshake failure, or no network — inside fetchLegacyCLIVersionFromRepo, which is the fallback path of fetchCLIVersionFromRepo.

Common situations: Offline or corporate-proxy-restricted CI runners; a bad gitRef producing an invalid URL; GitHub being unreachable or rate-limiting at the TCP/TLS layer; typos in the repo host configured for the bundler.

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 github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/2b2575089c736cfc. Report an issue: GitHub.

Appendix: source

Thrown at go/cmd/bundler/main.go:354

	if err := json.NewDecoder(resp.Body).Decode(&packageJSON); err != nil {
		return "", fmt.Errorf("failed to parse package.json: %w", err)
	}

	if packageJSON.CopilotCLIVersion == "" {
		return fetchLegacyCLIVersionFromRepo(gitRef)
	}

	return packageJSON.CopilotCLIVersion, nil
}

func fetchLegacyCLIVersionFromRepo(gitRef string) (string, error) {
	url := fmt.Sprintf(packageLockURLFmt, gitRef)
	fmt.Printf("Falling back to %s...\n", url)

	resp, err := http.Get(url)
	if err != nil {
		return "", fmt.Errorf("failed to fetch legacy package-lock.json: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("failed to fetch legacy package-lock.json: %s", resp.Status)
	}

	var packageLock struct {
		Packages map[string]struct {
			Version string `json:"version"`
		} `json:"packages"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&packageLock); err != nil {
		return "", fmt.Errorf("failed to parse legacy package-lock.json: %w", err)
	}
	pkg, ok := packageLock.Packages["node_modules/@github/copilot"]
	if !ok || pkg.Version == "" {
		return "", fmt.Errorf("could not find copilotCliVersion in package.json or @github/copilot in package-lock.json")
	}

View on GitHub (pinned to cd8cf15dc3)