MHSanaei/3x-ui · error
GitHub API returned status %d: %s
Error message
GitHub API returned status %d: %s
What it means
Returned by the same release-list fetch when the response is non-200 but the body has no parseable "message" JSON field, so only the status code and resp.Status can be reported. Covers non-GitHub-shaped failures: proxy error pages, HTML block pages, 5xx bodies. Distinguishes transport-level rejection from GitHub's structured errors (which produce the 'GitHub API error' variant).
Source
Thrown at internal/web/service/server.go:800
if reqErr != nil {
return nil, reqErr
}
resp, err := s.settingService.NewProxiedHTTPClient(10 * time.Second).Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// Check HTTP status code - GitHub API returns object instead of array on error
if resp.StatusCode != http.StatusOK {
bodyBytes, _ := io.ReadAll(resp.Body)
var errorResponse struct {
Message string `json:"message"`
}
if json.Unmarshal(bodyBytes, &errorResponse) == nil && errorResponse.Message != "" {
return nil, fmt.Errorf("GitHub API error: %s", errorResponse.Message)
}
return nil, fmt.Errorf("GitHub API returned status %d: %s", resp.StatusCode, resp.Status)
}
buffer := bytes.NewBuffer(make([]byte, bufferSize))
buffer.Reset()
if _, err := buffer.ReadFrom(resp.Body); err != nil {
return nil, err
}
var releases []Release
if err := json.Unmarshal(buffer.Bytes(), &releases); err != nil {
return nil, err
}
var versions []string
for _, release := range releases {
tagVersion := strings.TrimPrefix(release.TagName, "v")
tagParts := strings.Split(tagVersion, ".")
if len(tagParts) != 3 {View on GitHub (pinned to ad32144c42)
Solutions
- curl -si https://api.github.com/repos/XTLS/Xray-core/releases from the host to see the raw status and body
- Fix the panel's proxy settings (Settings → proxy) so the API is reachable, or bypass it
- Retry during a GitHub incident after checking githubstatus.com
Defensive patterns
Strategy: try-catch
Try / catch
versions, err := svc.GetXrayVersions()
if err != nil {
var statusErr = err // matches "GitHub API returned status"
if strings.Contains(statusErr.Error(), "returned status 5") {
return retryable(err) // 5xx is transient
}
return fatal(err)
}
Prevention
- Test egress to api.github.com (curl -si) before debugging deeper
- Keep the panel's outbound proxy configuration correct for both api.github.com and githubusercontent.com
- Retry only 5xx/429; treat 401/403 as configuration errors
When it happens
Trigger: An intercepting proxy answers api.github.com with a plain 502/503 HTML page; GitHub outage returning 5xx without a JSON envelope; a captive portal returning 302-followed HTML.
Common situations: Panels behind corporate proxies or in regions where api.github.com is filtered; transient GitHub incidents; misconfigured outbound proxy for the panel.
Related errors
- GitHub API returned status %d: %s
- GitHub API error: %s
- download xray: unexpected HTTP %d
- download xray checksum: unexpected HTTP %d
- xray version %q is not in the fetched release list
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/17ae5b1c498031a7.
Report an issue: GitHub.