MHSanaei/3x-ui · warning

bad ss host:port

Error message

bad ss host:port

What it means

Returned by parseShadowsocks for a SIP002-form link (ss://base64userinfo@host:port) when, after taking the part after the last '@' and trimming trailing '/', there is no ':' at all — the parser cannot split host from port. Hostname-only or IPv6-without-brackets links are the usual culprits, since the code splits on the LAST colon and expects 'host:port' text.

Source

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

	}
	core := strings.TrimPrefix(link, "ss://")
	at := strings.Index(core, "@")
	if at >= 0 {
		// modern
		userB64 := core[:at]
		hp := strings.TrimRight(core[at+1:], "/")
		userInfo, err := base64DecodeFlexible(userB64)
		if err != nil {
			// SIP022 (2022-blake3-*) userinfo is percent-encoded, not base64.
			if dec, uerr := url.QueryUnescape(userB64); uerr == nil {
				userInfo = dec
			} else {
				userInfo = userB64 // not b64, rare
			}
		}
		colon := strings.LastIndex(hp, ":")
		if colon < 0 {
			return nil, fmt.Errorf("bad ss host:port")
		}
		host := hp[:colon]
		port, err := strconv.Atoi(hp[colon+1:])
		if err != nil {
			return nil, fmt.Errorf("bad ss port %q: %w", hp[colon+1:], err)
		}
		method, pass := splitMethodPass(userInfo)
		identity := "ss:" + method + ":" + pass + "@" + host + ":" + strconv.Itoa(port)
		ob := Outbound{
			"protocol": "shadowsocks",
			"tag":      remark,
			"settings": map[string]any{
				"servers": []any{
					map[string]any{"address": host, "port": port, "password": pass, "method": method},
				},
			},
		}
		return &ParseResult{Outbound: ob, Identity: identity}, nil

View on GitHub (pinned to ad32144c42)

Solutions

  1. Inspect the link after '@': it must look like host:443 (or [v6host]:443).
  2. Wrap IPv6 hosts in square brackets and always include an explicit port.
  3. Re-export the link from the source client's share function.
  4. For batch imports, validate with a regexp like ^ss://[^@]+@[^@]+:\d+ before parsing.

Example fix

// before
ss://YWVzLTI1Ni1nY206cGFzcw==@example.com

// after
ss://YWVzLTI1Ni1nY206cGFzcw==@example.com:8388
Defensive patterns

Strategy: validation

Validate before calling

var sip002Re = regexp.MustCompile(`^ss://[^@]+@([a-zA-Z0-9.\-]+|\[[^]]+\]):\d{1,5}`)
func looksLikeValidSIP002(link string) bool { return sip002Re.MatchString(strings.TrimSpace(link)) }

Prevention

When it happens

Trigger: Link truncated before the port ('ss://xxx@host'); IPv6 host written without square brackets followed by port, or with brackets but no ':port' after; a remark fragment swallowing the port (ss://xxx@host#remark where '/' trimming already failed); plain host with no port.

Common situations: Hand-typed or sed-edited ss links; providers emitting 'ss://method:pass@host' with the port dropped; IPv6 servers exported by clients that omit brackets in the userinfo form.

Related errors


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