MHSanaei/3x-ui · warning

not hysteria2

Error message

not hysteria2

What it means

Returned by parseHysteria2 when the parsed URL's scheme is neither 'hysteria2' nor 'hy2'. Like the vless/trojan guards, ParseOutbound only forwards links with those two prefixes, so this indicates a direct call to parseHysteria2 or a custom dispatcher routing a hysteria-variant scheme (hysteria:// v1, hy3://) into it.

Source

Thrown at internal/util/link/outbound.go:435

}

func splitMethodPass(userInfo string) (string, string) {
	before, after, ok := strings.Cut(userInfo, ":")
	if !ok {
		return "2022-blake3-aes-128-gcm", userInfo // guess
	}
	return before, after
}

// --- hysteria2 ---

func parseHysteria2(link string) (*ParseResult, error) {
	u, err := url.Parse(link)
	if err != nil {
		return nil, err
	}
	if u.Scheme != "hysteria2" && u.Scheme != "hy2" {
		return nil, fmt.Errorf("not hysteria2")
	}
	auth := u.User.Username()
	host := u.Hostname()
	port := defaultPort(u.Port(), 443)
	params := u.Query()

	stream := map[string]any{
		"network":  "hysteria",
		"security": "tls",
		"hysteriaSettings": map[string]any{
			"version":        2,
			"auth":           auth,
			"udpIdleTimeout": 60,
		},
		"tlsSettings": map[string]any{
			"serverName":           params.Get("sni"),
			"alpn":                 splitCommaOrDefault(params.Get("alpn"), []string{"h3"}),
			"fingerprint":          params.Get("fp"),

View on GitHub (pinned to ad32144c42)

Solutions

  1. Dispatch on the exact prefixes 'hysteria2://' and 'hy2://' (case-normalized), and use ParseOutbound publicly.
  2. Give hysteria v1 (hysteria://) its own parser — its query params (auth, upmbps, alpn) differ from v2.
  3. Reject or skip v1 links in batch imports rather than routing them to the v2 parser.

Example fix

// before
case strings.Contains(link, "hysteria"):
    return parseHysteria2(link)

// after
case strings.HasPrefix(link, "hysteria2://"), strings.HasPrefix(link, "hy2://"):
    return parseHysteria2(link)
Defensive patterns

Strategy: validation

Validate before calling

func isHysteria2Link(link string) bool {
    u, err := url.Parse(strings.TrimSpace(link))
    if err != nil { return false }
    s := strings.ToLower(u.Scheme)
    return s == "hysteria2" || s == "hy2"
}

Prevention

When it happens

Trigger: Routing hysteria v1 links (hysteria://) to parseHysteria2 — v1 has an entirely different param format; dispatching on substring 'hy' or 'hysteria' without the exact prefix; direct parser calls in tests or forks.

Common situations: Subscriptions mixing hysteria v1 and v2 entries; forks adding v1 support and reusing the v2 parser; prefix tables matching 'hy2' case-sensitively while a provider emits 'HY2://'.

Related errors


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