plandex-ai/plandex · error

failed to download the update: %w

Error message

failed to download the update: %w

What it means

doUpgrade in the Plandex CLI downloads the new release tarball from GitHub Releases via http.Get. If the HTTP request itself fails at the transport level (DNS failure, connection refused, TLS error, timeout), it wraps the net/http error with 'failed to download the update: %w'. This is thrown before any HTTP status is examined, so it only covers request-send failures, not 404s.

Source

Thrown at app/cli/upgrade.go:106

				term.OutputErrorAndExit("Failed to upgrade: %v", err)
				return
			}
			term.StopSpinner()
			restartPlandex()
		} else {
			fmt.Println("Note: set PLANDEX_SKIP_UPGRADE=1 to stop upgrade prompts")
		}
	}
}

func doUpgrade(version string) error {
	tag := fmt.Sprintf("cli/v%s", version)
	escapedTag := url.QueryEscape(tag)

	downloadURL := fmt.Sprintf("https://github.com/plandex-ai/plandex/releases/download/%s/plandex_%s_%s_%s.tar.gz", escapedTag, version, runtime.GOOS, runtime.GOARCH)
	resp, err := http.Get(downloadURL)
	if err != nil {
		return fmt.Errorf("failed to download the update: %w", err)
	}
	defer resp.Body.Close()

	// Create a temporary file to save the downloaded archive
	tempFile, err := os.CreateTemp("", "*.tar.gz")
	if err != nil {
		return fmt.Errorf("failed to create temporary file: %w", err)
	}
	defer os.Remove(tempFile.Name()) // Clean up file afterwards

	// Copy the response body to the temporary file
	_, err = io.Copy(tempFile, resp.Body)
	if err != nil {
		return fmt.Errorf("failed to save the downloaded archive: %w", err)
	}

	_, err = tempFile.Seek(0, 0)
	if err != nil {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Restore network connectivity to github.com (check DNS, proxy, VPN, firewall).
  2. Set HTTPS_PROXY/HTTP_PROXY if behind a corporate proxy.
  3. Retry the upgrade later or download and install the release manually.
  4. Set PLANDEX_SKIP_UPGRADE=1 to bypass the upgrade prompt entirely.

Example fix

// before (hard failure on any transport error)
resp, err := http.Get(downloadURL)
if err != nil {
	return fmt.Errorf("failed to download the update: %w", err)
}
// after (client with timeout; retry on transient failure)
client := &http.Client{Timeout: 60 * time.Second}
var resp *http.Response
var err error
for i := 0; i < 3; i++ {
	resp, err = client.Get(downloadURL)
	if err == nil {
		break
	}
	time.Sleep(2 * time.Second)
}
if err != nil {
	return fmt.Errorf("failed to download the update: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

url := fmt.Sprintf("https://github.com/plandex-ai/plandex/releases/download/cli/v%s/plandex_%s_%s_%s.tar.gz", ver, ver, runtime.GOOS, runtime.GOARCH)
if _, err := net.DialTimeout("tcp", "github.com:443", 3*time.Second); err != nil {
	return fmt.Errorf("github.com unreachable: %w", err)
}

Try / catch

var resp *http.Response
var err error
for attempt := 0; attempt < 3; attempt++ {
	resp, err = http.Get(downloadURL)
	if err == nil {
		break
	}
	time.Sleep(time.Duration(1<<attempt) * time.Second)
}
if err != nil {
	fmt.Printf("upgrade skipped: %v\n", err) // degrade gracefully
}

Prevention

When it happens

Trigger: checkForUpgrade detects a newer version, user confirms the upgrade, and http.Get on the GitHub Releases download URL fails at the transport layer — no network connectivity, DNS resolution failure, proxy/firewall blocking github.com, or TLS handshake error.

Common situations: Offline or corporate-proxy environments where github.com is unreachable; DNS misconfiguration; VPN dropouts; GitHub outage; IPv6 misconfig.

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 plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/59a158b5027d17cb. Report an issue: GitHub.