abiosoft/colima · error

invalid URL '%s': %w

Error message

invalid URL '%s': %w

What it means

GetFinalURL builds a HEAD request from rawURL and http.NewRequestWithContext rejected the URL string before any network traffic: it does not parse as a request target (control characters, invalid percent-escapes, missing/unsupported scheme). This is a malformed-input error, not a network failure.

Source

Thrown at util/downloader/http.go:76

		ResponseHeaderTimeout: 30 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}

	return &HTTPClient{
		client: &http.Client{
			Transport: transport,
			// checkRedirect is left default - Go follows up to 10 redirects
			// and returns the final response
		},
		userAgent: "colima/" + config.AppVersion().Version,
	}
}

// GetFinalURL follows redirects and returns the final URL
func (h *HTTPClient) GetFinalURL(ctx context.Context, rawURL string) (string, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodHead, rawURL, nil)
	if err != nil {
		return "", fmt.Errorf("invalid URL '%s': %w", rawURL, err)
	}
	req.Header.Set("User-Agent", h.userAgent)

	resp, err := h.client.Do(req)
	if err != nil {
		return "", &NetworkError{Op: "resolve redirect", URL: rawURL, Err: err}
	}
	defer func() { _ = resp.Body.Close() }()

	// check for HTTP errors
	if resp.StatusCode >= 400 {
		return "", &HTTPStatusError{
			StatusCode: resp.StatusCode,
			Status:     resp.Status,
			URL:        rawURL,
		}
	}

View on GitHub (pinned to c3a5f9184d)

Solutions

  1. Validate with url.ParseRequestURI before calling GetFinalURL and reject non-http(s) schemes
  2. Trim whitespace and percent-encode dynamic path segments with url.PathEscape
  3. Log the raw URL: the %s in the message shows the exact offending string
  4. Reproduce with curl -I <url> — curl fails loudly on the same malformed input

Example fix

// before
finalURL, err := client.GetFinalURL(ctx, u)
// after
u = strings.TrimSpace(u)
if _, err := url.ParseRequestURI(u); err != nil {
    return fmt.Errorf("invalid download url %q: %w", u, err)
}
finalURL, err := client.GetFinalURL(ctx, u)
Defensive patterns

Strategy: validation

Validate before calling

u := strings.TrimSpace(rawURL)
if _, err := url.ParseRequestURI(u); err != nil {
    return fmt.Errorf("invalid download url %q: %w", u, err)
}
parsed, err := url.Parse(u)
if err != nil || (parsed.Scheme != "http" && parsed.Scheme != "https") {
    return fmt.Errorf("url must be absolute http(s): %q", u)
}
finalURL, err := client.GetFinalURL(ctx, u)

Prevention

When it happens

Trigger: Passing a URL containing spaces, tabs, or newlines (e.g. concatenated with an unescaped version string like '1.0 beta'), invalid % sequences, or no scheme; url.ParseRequestURI fails on the same input.

Common situations: Templated download URLs with unescaped dynamic segments; env-provided URLs with trailing whitespace; copy-paste from docs adding invisible characters.

Related errors


AI-assisted analysis of abiosoft/colima@c3a5f9184d (2026-08-15). Data as JSON: /api/errors/7e66c9b8a303a4eb. Report an issue: GitHub.