{"record":{"id":"46421e6ceef66885","repo":"MHSanaei/3x-ui","slug":"http-d","errorCode":null,"errorMessage":"http %d","messagePattern":"http %d","errorType":"http","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/web/service/outbound_subscription.go","lineNumber":376,"sourceCode":"\t}\n\n\treqCtx := netsafe.ContextWithAllowPrivate(context.Background(), sub.AllowPrivate)\n\treq, err := http.NewRequestWithContext(reqCtx, http.MethodGet, sub.Url, nil)\n\tif err != nil {\n\t\ts.recordError(sub, err)\n\t\treturn nil, err\n\t}\n\treq.Header.Set(\"User-Agent\", \"3x-ui-outbound-sub/1.0\")\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\ts.recordError(sub, err)\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\terr := fmt.Errorf(\"http %d\", resp.StatusCode)\n\t\ts.recordError(sub, err)\n\t\treturn nil, err\n\t}\n\tbody, err := readBoundedOutboundSubscriptionBody(resp.Body)\n\tif err != nil {\n\t\ts.recordError(sub, err)\n\t\treturn nil, err\n\t}\n\n\tparsed, identities, err := link.ParseSubscriptionBody(body)\n\tif err != nil {\n\t\ts.recordError(sub, err)\n\t\treturn nil, err\n\t}\n\n\t// Load previous identities -> tags for stability\n\tprev := map[string]string{}\n\tif strings.TrimSpace(sub.LinkIdentities) != \"\" {","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/service/outbound_subscription.go#L358-L394","documentation":"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.","triggerScenarios":"Refresh/update of an outbound subscription where the server answers 401, 403, 404, 429, 5xx, etc.","commonSituations":"Expired or rotated subscription token; URL typo; provider rate-limiting automated fetches; Cloudflare challenge page returning 403.","solutions":["Reproduce with the same User-Agent to see the code: curl -sI -A '3x-ui-outbound-sub/1.0' <url>","401/403 -> get a fresh subscription URL/token from the provider","429 -> slow down the refresh schedule (subscription auto-update interval)","5xx -> provider-side outage; retry later"],"exampleFix":"curl -sI -A '3x-ui-outbound-sub/1.0' 'https://provider.example/sub?key=OLD'\n# HTTP/2 401  -> regenerate the link in the provider dashboard, paste the new URL into the outbound subscription","handlingStrategy":"retry","validationCode":"resp, err := client.Get(sub.Url)\nif err == nil {\n    defer resp.Body.Close()\n    if resp.StatusCode == http.StatusOK {\n        // only now hand to the service\n    }\n}","typeGuard":null,"tryCatchPattern":"_, err := client.Do(req)\nif err != nil {\n    var httpErr error\n    if strings.HasPrefix(err.Error(), \"http \") { /* actually returned by service, not transport */ }\n    // 429/5xx: retry with backoff; 401/403/404: surface 'subscription URL invalid'\n}","preventionTips":["Set a sane auto-refresh interval to avoid 429s","Rotate subscription tokens promptly when providers expire them"],"tags":["http-status","network","subscriptions","authentication"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}