MHSanaei/3x-ui · warning

http %d

Error message

http %d

What it means

After fetching the subscription, any status other than HTTP 200 is collapsed into 'http %d', recorded against the subscription via recordError (visible in the panel's last-error field), and returned. Common codes: 401/403 (bad token), 404 (wrong URL), 429 (rate limit), 5xx (provider down). The body is not read for a hint — the numeric code is the whole diagnostic.

Source

Thrown at internal/web/service/outbound_subscription.go:376

	}

	reqCtx := netsafe.ContextWithAllowPrivate(context.Background(), sub.AllowPrivate)
	req, err := http.NewRequestWithContext(reqCtx, http.MethodGet, sub.Url, nil)
	if err != nil {
		s.recordError(sub, err)
		return nil, err
	}
	req.Header.Set("User-Agent", "3x-ui-outbound-sub/1.0")

	resp, err := client.Do(req)
	if err != nil {
		s.recordError(sub, err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		err := fmt.Errorf("http %d", resp.StatusCode)
		s.recordError(sub, err)
		return nil, err
	}
	body, err := readBoundedOutboundSubscriptionBody(resp.Body)
	if err != nil {
		s.recordError(sub, err)
		return nil, err
	}

	parsed, identities, err := link.ParseSubscriptionBody(body)
	if err != nil {
		s.recordError(sub, err)
		return nil, err
	}

	// Load previous identities -> tags for stability
	prev := map[string]string{}
	if strings.TrimSpace(sub.LinkIdentities) != "" {

View on GitHub (pinned to ad32144c42)

Solutions

  1. Reproduce with the same User-Agent to see the code: curl -sI -A '3x-ui-outbound-sub/1.0' <url>
  2. 401/403 -> get a fresh subscription URL/token from the provider
  3. 429 -> slow down the refresh schedule (subscription auto-update interval)
  4. 5xx -> provider-side outage; retry later

Example fix

curl -sI -A '3x-ui-outbound-sub/1.0' 'https://provider.example/sub?key=OLD'
# HTTP/2 401  -> regenerate the link in the provider dashboard, paste the new URL into the outbound subscription
Defensive patterns

Strategy: retry

Validate before calling

resp, err := client.Get(sub.Url)
if err == nil {
    defer resp.Body.Close()
    if resp.StatusCode == http.StatusOK {
        // only now hand to the service
    }
}

Try / catch

_, err := client.Do(req)
if err != nil {
    var httpErr error
    if strings.HasPrefix(err.Error(), "http ") { /* actually returned by service, not transport */ }
    // 429/5xx: retry with backoff; 401/403/404: surface 'subscription URL invalid'
}

Prevention

When it happens

Trigger: Refresh/update of an outbound subscription where the server answers 401, 403, 404, 429, 5xx, etc.

Common situations: Expired or rotated subscription token; URL typo; provider rate-limiting automated fetches; Cloudflare challenge page returning 403.

Related errors


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