MHSanaei/3x-ui · warning

bad legacy ss port %q: %w

Error message

bad legacy ss port %q: %w

What it means

Returned by the legacy ss branch when the decoded host:port part has a colon but the text after the last colon fails strconv.Atoi — the port is present yet not a plain integer. The message quotes the bad port text, making the offending segment immediately visible.

Source

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

	// legacy: whole thing b64
	dec, err := base64DecodeFlexible(core)
	if err != nil {
		return nil, err
	}
	at = strings.Index(dec, "@")
	if at < 0 {
		return nil, fmt.Errorf("bad legacy ss")
	}
	userInfo := dec[:at]
	hp := dec[at+1:]
	colon := strings.LastIndex(hp, ":")
	if colon < 0 {
		return nil, fmt.Errorf("bad legacy ss hp")
	}
	host := hp[:colon]
	port, err := strconv.Atoi(hp[colon+1:])
	if err != nil {
		return nil, fmt.Errorf("bad legacy 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
}

func splitMethodPass(userInfo string) (string, string) {
	before, after, ok := strings.Cut(userInfo, ":")
	if !ok {

View on GitHub (pinned to ad32144c42)

Solutions

  1. Read the quoted value in the error message — it is exactly what failed to parse as an integer.
  2. Fix the payload to method:password@host:PORT with a numeric port and re-base64 it.
  3. Move remarks into the fragment (#) instead of a colon suffix.
  4. Bracket IPv6 hosts in the payload.

Example fix

// before (payload: aes-256-gcm:pass@example.com:https)
ss://...

// after (payload: aes-256-gcm:pass@example.com:443)
ss://YWVzLTI1Ni1nY206cGFzc0BleGFtcGxlLmNvbTo0NDM=
Defensive patterns

Strategy: validation

Validate before calling

func legacySSPortIsNumeric(link string) bool {
    core := strings.TrimPrefix(link, "ss://")
    dec, err := base64DecodeFlexible(core)
    if err != nil { return false }
    i := strings.LastIndex(dec, ":")
    if i < 0 { return false }
    _, err = strconv.Atoi(dec[i+1:])
    return err == nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "bad legacy ss port") {
    // message quotes the bad segment: rewrite payload with a numeric port and re-encode
}

Prevention

When it happens

Trigger: Port written as a service name ('ssh') or empty; trailing remark glued on with ':' (method:pass@host:443:remark); IPv6 without brackets making a hex group the 'port'; leftover path text after the port.

Common situations: The same hand-edited or provider-quirky legacy links as the other legacy errors; double separators from concatenation scripts; payloads decoded with the wrong base64 variant producing near-miss strings.

Related errors


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