{"record":{"id":"cd017e983caa728a","repo":"MHSanaei/3x-ui","slug":"outbound-subscription-response-body-exceeds-size-l","errorCode":null,"errorMessage":"outbound subscription response body exceeds size limit","messagePattern":"outbound subscription response body exceeds size limit","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/web/service/outbound_subscription.go","lineNumber":61,"sourceCode":"\t\t\t\tif m, ok := ob.(map[string]any); ok {\n\t\t\t\t\ttag, _ = m[\"tag\"].(string)\n\t\t\t\t}\n\t\t\t\tlogger.Warningf(\"%s: dropping outbound %q rejected by xray-core: %v\", label, tag, buildErr)\n\t\t\t\tdropped = append(dropped, fmt.Sprintf(\"%s: %v\", tag, buildErr))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tkept = append(kept, ob)\n\t}\n\treturn kept, dropped\n}\n\n// maxOutboundSubscriptionBytes caps a single outbound subscription response.\n// It is larger than the 2 MiB user-facing subscription cap because an outbound\n// subscription may aggregate many upstream outbounds into one document.\nconst maxOutboundSubscriptionBytes int64 = 8 << 20\n\nvar errOutboundSubscriptionBodyTooLarge = errors.New(\"outbound subscription response body exceeds size limit\")\n\nfunc readBoundedOutboundSubscriptionBody(r io.Reader) ([]byte, error) {\n\tbody, err := io.ReadAll(io.LimitReader(r, maxOutboundSubscriptionBytes+1))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif int64(len(body)) > maxOutboundSubscriptionBytes {\n\t\treturn nil, fmt.Errorf(\"%w (limit: %d bytes)\", errOutboundSubscriptionBodyTooLarge, maxOutboundSubscriptionBytes)\n\t}\n\treturn body, nil\n}\n\n// OutboundSubscriptionService manages remote outbound subscriptions.\ntype OutboundSubscriptionService struct {\n\tsettingService SettingService\n}\n\n// NewOutboundSubscriptionService returns a service for managing outbound subscriptions.","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/service/outbound_subscription.go#L43-L79","documentation":"errOutboundSubscriptionBodyTooLarge is returned by readBoundedOutboundSubscriptionBody in internal/web/service/outbound_subscription.go when a fetched outbound subscription document exceeds maxOutboundSubscriptionBytes (8 MiB). The 8 MiB cap is deliberately larger than the 2 MiB user-facing subscription cap because outbound subscriptions aggregate many upstream outbounds into one document; crossing it means the upstream feed is abnormally large or hostile.","triggerScenarios":"The outbound-subscription refresh job (or manual fetch of an outbound subscription URL) downloads a body larger than 8 MiB — e.g. a provider URL that now returns thousands of outbounds, an accidentally pasted wrong URL serving a huge file, or a server that ignores range/size expectations.","commonSituations":"Subscribing to a mega-aggregator provider list; the subscription URL pointing at a binary/artifact file instead of a config; a compromised or misconfigured upstream serving endless data.","solutions":["Fetch the URL with curl and check the actual size and content; confirm it is a valid outbound subscription document","Trim the subscription at the provider side or point at a filtered/sliced URL that fits under 8 MiB","If the feed is legitimately larger, raise maxOutboundSubscriptionBytes and rebuild, then re-test the refresh job","Remove the offending subscription entry if it was added by mistake"],"exampleFix":"// before\nconst maxOutboundSubscriptionBytes int64 = 8 << 20\n\n// after\nconst maxOutboundSubscriptionBytes int64 = 16 << 20","handlingStrategy":"try-catch","validationCode":"resp, err := http.Get(subURL)\nif err == nil {\n    if resp.ContentLength > maxOutboundSubscriptionBytes {\n        resp.Body.Close()\n        return errOutboundSubscriptionBodyTooLarge\n    }\n    defer resp.Body.Close()\n}","typeGuard":"func isOutboundSubTooLarge(err error) bool {\n    return errors.Is(err, errOutboundSubscriptionBodyTooLarge)\n}","tryCatchPattern":"body, err := readBoundedOutboundSubscriptionBody(resp.Body)\nif err != nil {\n    if errors.Is(err, errOutboundSubscriptionBodyTooLarge) {\n        // drop or quarantine this subscription; do not retry in a tight loop\n    }\n    return err\n}","preventionTips":["Pre-check Content-Length when the server provides it","Validate subscription URLs at entry time (scheme, expected host, rough size)","Alert on subscriptions that grow steadily toward the 8 MiB cap"],"tags":["network","size-limit","subscription","outbound"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}