XTLS/Xray-core · error
unexpected HTTP status code: %d
Error message
unexpected HTTP status code: %d
What it means
After a successful fetch, fetchHTTPContent requires exactly HTTP 200; any other status — including other 2xx codes like 204, and all redirects that aren't auto-followed for hand-built requests — is rejected with the numeric code.
Source
Thrown at main/commands/all/api/shared.go:100
if s := strings.ToLower(parsedTarget.Scheme); s != "http" && s != "https" {
return nil, fmt.Errorf("invalid scheme: %s", parsedTarget.Scheme)
}
client := &http.Client{
Timeout: 30 * time.Second,
}
resp, err := client.Do(&http.Request{
Method: "GET",
URL: parsedTarget,
Close: true,
})
if err != nil {
return nil, fmt.Errorf("failed to dial to %s", target)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("unexpected HTTP status code: %d", resp.StatusCode)
}
content, err := buf.ReadAllToBytes(resp.Body)
if err != nil {
return nil, errors.New("failed to read HTTP response")
}
return content, nil
}
func showJSONResponse(m proto.Message) {
if isNil(m) {
return
}
if j, ok := creflect.MarshalToJson(m, true); ok {
fmt.Println(j)
} else {
fmt.Fprintf(os.Stdout, "%v\n", m)View on GitHub (pinned to 7d214f8b09)
Solutions
- curl -I the URL to see the actual status and Location header
- Update the URL to a current, direct (non-redirecting) source
- For 403: add a User-Agent or use a different mirror if the server filters clients
- Host the file locally to remove the dependency
Example fix
# before: 404 "downloadUrl": "https://old-mirror/geoip.dat" # after (verified with curl -I → 200) "downloadUrl": "https://new-mirror/geoip.dat"
Defensive patterns
Strategy: fallback
Validate before calling
// pre-flight: expect exactly 200
resp, err := http.Head(url)
if err == nil && resp.StatusCode != 200 {
return fmt.Errorf("source returned %d — pick another mirror", resp.StatusCode)
} Try / catch
body, err := fetchHTTPContent(target)
if err != nil && strings.Contains(err.Error(), "unexpected HTTP status code") {
for _, mirror := range mirrors { // fallback list
if body, err = fetchHTTPContent(mirror); err == nil { break }
}
} Prevention
- Only 200 counts as success — even 204/206 fail
- Prefer stable direct-download URLs over redirecting mirrors
- Verify links with curl -I during config authoring
When it happens
Trigger: Server returns 403/404/5xx for the resource URL; a 204 or 206 response; a redirect (301/302) that the constructed http.Request did not follow because the URL host/path changed or the client's redirect policy was hit.
Common situations: Geo resource moved or removed upstream (404); CDN rate-limiting or geo-blocking (403); authenticated endpoints returning 401; mirrors returning redirects to signed URLs.
Related errors
- failed to dial to
- unexpected HTTP status code:
- invalid scheme: %s
- failed to dial to %s
- LRU size is bigger than subnet size
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/067c5799a24ae42b.
Report an issue: GitHub.