{"record":{"id":"358fcb91a0eea9b1","repo":"MHSanaei/3x-ui","slug":"bad-ss-port-q-w","errorCode":null,"errorMessage":"bad ss port %q: %w","messagePattern":"bad ss port %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/util/link/outbound.go","lineNumber":370,"sourceCode":"\t\tuserB64 := core[:at]\n\t\thp := strings.TrimRight(core[at+1:], \"/\")\n\t\tuserInfo, err := base64DecodeFlexible(userB64)\n\t\tif err != nil {\n\t\t\t// SIP022 (2022-blake3-*) userinfo is percent-encoded, not base64.\n\t\t\tif dec, uerr := url.QueryUnescape(userB64); uerr == nil {\n\t\t\t\tuserInfo = dec\n\t\t\t} else {\n\t\t\t\tuserInfo = userB64 // not b64, rare\n\t\t\t}\n\t\t}\n\t\tcolon := strings.LastIndex(hp, \":\")\n\t\tif colon < 0 {\n\t\t\treturn nil, fmt.Errorf(\"bad ss host:port\")\n\t\t}\n\t\thost := hp[:colon]\n\t\tport, err := strconv.Atoi(hp[colon+1:])\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"bad ss port %q: %w\", hp[colon+1:], err)\n\t\t}\n\t\tmethod, pass := splitMethodPass(userInfo)\n\t\tidentity := \"ss:\" + method + \":\" + pass + \"@\" + host + \":\" + strconv.Itoa(port)\n\t\tob := Outbound{\n\t\t\t\"protocol\": \"shadowsocks\",\n\t\t\t\"tag\":      remark,\n\t\t\t\"settings\": map[string]any{\n\t\t\t\t\"servers\": []any{\n\t\t\t\t\tmap[string]any{\"address\": host, \"port\": port, \"password\": pass, \"method\": method},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\treturn &ParseResult{Outbound: ob, Identity: identity}, nil\n\t}\n\t// legacy: whole thing b64\n\tdec, err := base64DecodeFlexible(core)\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/util/link/outbound.go#L352-L388","documentation":"Returned by parseShadowsocks (SIP002 branch) when the host part contains a colon, so parsing proceeds, but everything after the last colon is not a valid integer port (strconv.Atoi fails). The offending text is quoted in the message. Note the code already trimmed trailing '/', so a lone trailing slash is not the cause — the port segment itself is non-numeric.","triggerScenarios":"Port spelled as a service name ('https') or empty ('host:'); path/query text left inside the port segment ('host:443?obfs=xxx' or 'host:443/'); IPv6 without brackets making 'g.cm' the port; a remark appended with ':' instead of '#'.","commonSituations":"Providers appending plugin parameters in non-standard positions; users writing ss://user@host:https; copy-paste where the '#remark' turned into ':remark'.","solutions":["Look at the quoted value in the error — it shows exactly what the parser tried to read as the port.","Move anything after the port into the fragment: ss://...@host:443#remark, and plugin params into query ?plugin=...","Use a numeric port only (1-65535).","Bracket IPv6 hosts: [2001:db8::1]:443."],"exampleFix":"// before\nss://YWVzLTI1Ni1nY206cGFzcw==@example.com:https\n\n// after\nss://YWVzLTI1Ni1nY206cGFzcw==@example.com:443","handlingStrategy":"validation","validationCode":"// reject ss links whose port segment is non-numeric BEFORE parsing\nu, err := url.Parse(link)\nif err == nil && u.Scheme == \"ss\" {\n    if p := u.Port(); p == \"\" { return errors.New(\"missing or non-numeric ss port\") }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"bad ss port\") {\n    // the message quotes the bad text: fix the link's port segment and retry\n}","preventionTips":["Keep remarks in the # fragment and plugin params in the query string.","Use numeric ports 1-65535 only.","Never concatenate extra ':'-separated fields after the port."],"tags":["parsing","proxy-links","shadowsocks","port","validation"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}