MHSanaei/3x-ui · error

download xray checksum: %w

Error message

download xray checksum: %w

What it means

Returned by fetchXrayDigestSHA256 when http.NewRequestWithContext rejects the .dgst URL before any request is sent (%w wraps reqErr). The URL is mechanically built as the asset URL + ".dgst", so failure here means the constructed URL is not parseable — practically only possible when the base asset URL was already malformed or contains illegal characters. On success paths this error is unreachable.

Source

Thrown at internal/web/service/server.go:953

	}
	if got := hex.EncodeToString(hasher.Sum(nil)); !strings.EqualFold(got, want) {
		// User-facing warning: the archive's SHA-256 does not match the official
		// release checksum, so the download is corrupted or has been tampered
		// with. Abort the install so a bad binary is never run, and tell the user
		// to retry/re-download rather than proceed with a mismatched image.
		return "", fmt.Errorf("Xray update aborted: the downloaded archive does not match the official SHA-256 checksum, so the image is corrupted or differs from the official release. Please exit and re-download the official image, then try again (expected %s, got %s)", want, got)
	}

	ok = true
	return path, nil
}

// fetchXrayDigestSHA256 downloads the .dgst sidecar XTLS publishes next to each
// release asset and returns the SHA2-256 hex digest it lists.
func (s *ServerService) fetchXrayDigestSHA256(client *http.Client, dgstURL string) (string, error) {
	req, reqErr := http.NewRequestWithContext(context.Background(), http.MethodGet, dgstURL, nil)
	if reqErr != nil {
		return "", fmt.Errorf("download xray checksum: %w", reqErr)
	}
	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("download xray checksum: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("download xray checksum: unexpected HTTP %d", resp.StatusCode)
	}
	raw, err := io.ReadAll(io.LimitReader(resp.Body, maxXrayDigestBytes))
	if err != nil {
		return "", fmt.Errorf("download xray checksum: %w", err)
	}
	return parseXrayDigestSHA256(raw)
}

// parseXrayDigestSHA256 extracts the lowercase SHA2-256 hex from an XTLS .dgst
// file, whose lines are "ALGO= <hex>" (the relevant one being "SHA2-256= ...").

View on GitHub (pinned to ad32144c42)

Solutions

  1. Inspect the exact version string passed to UpdateXray for whitespace/control characters
  2. Pre-validate versions against the release list (the code already does via slices.Contains) before manual calls
  3. Treat this error as a code smell: log the URL being built when it fires
Defensive patterns

Strategy: validation

Validate before calling

if _, err := url.ParseRequestURI(dgstURL); err != nil {
    return fmt.Errorf("refusing to fetch malformed digest URL %q: %w", dgstURL, err)
}

Prevention

When it happens

Trigger: A version string with control characters or spaces slotted into the URL template; a corrupted base URL from upstream configuration; test harnesses injecting invalid URLs.

Common situations: Almost never seen in production; appears in tests or when version input is not sanitized before UpdateXray.

Related errors


AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15). Data as JSON: /api/errors/d8bc078e1518abc3. Report an issue: GitHub.