XTLS/Xray-core · error · errors.Error

unexpected status code:

Error message

unexpected status code: 

What it means

Returned by downloadOne after a geodata HTTP response arrives with a status code outside 200-299. The body is drained/discarded and the numeric status is embedded in the message.

Source

Thrown at app/geodata/download.go:213

		return err
	}
	utils.TryDefaultHeadersWith(req.Header, "nav")

	var client *http.Client
	if req.URL.Scheme == "https" {
		client = d.httpsClient
	} else {
		client = d.httpClient
	}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
		io.Copy(io.Discard, resp.Body)
		return errors.New("unexpected status code: ", resp.StatusCode)
	}

	n, err := io.Copy(writer, resp.Body)
	if err != nil {
		return err
	}
	if n == 0 {
		return errors.New("empty response body")
	}
	return nil
}

func clean(assets []stage) {
	for _, asset := range assets {
		if asset.temp != "" {
			os.Remove(asset.temp)
		}
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Open the exact asset URL in a browser/curl to confirm it returns 200
  2. For 403/429 rate limiting, switch mirrors or add delay between updates (widen the geodata cron)
  3. For 404, correct the asset path or use the default asset URLs
  4. Retry later for 5xx outages
Defensive patterns

Strategy: try-catch

Validate before calling

// Health-check the asset URL before the cron fires:
resp, err := http.Head(assetURL)
if err != nil || resp.StatusCode < 200 || resp.StatusCode >= 300 {
    // mark mirror unhealthy, use fallback URL
}

Try / catch

resp, err := client.Do(req)
if err == nil && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
    switch resp.StatusCode {
    case 403, 429:
        time.Sleep(time.Minute) // rate limited: back off before retry
    case 404:
        return fmt.Errorf("asset missing at %s; fix URL", req.URL) // permanent
    default:
        // transient 5xx: retry later
    }
}

Prevention

When it happens

Trigger: client.Do for a geodata asset returns e.g. 404 (file removed / wrong path), 403 (rate limited or blocked CDN), 5xx (mirror outage), or 301 leaking through when redirects were stopped.

Common situations: Wrong asset URL path after a repo reorganization; GitHub raw rate limiting; mirror temporarily down; asset name typo like 'geosites.dat' instead of 'geosite.dat'.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/5497f2281cc76f69. Report an issue: GitHub.