{"record":{"id":"641fc9a86b2359e5","repo":"MHSanaei/3x-ui","slug":"bad-legacy-ss-hp","errorCode":null,"errorMessage":"bad legacy ss hp","messagePattern":"bad legacy ss hp","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/util/link/outbound.go","lineNumber":398,"sourceCode":"\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\n\t}\n\tat = strings.Index(dec, \"@\")\n\tif at < 0 {\n\t\treturn nil, fmt.Errorf(\"bad legacy ss\")\n\t}\n\tuserInfo := dec[:at]\n\thp := dec[at+1:]\n\tcolon := strings.LastIndex(hp, \":\")\n\tif colon < 0 {\n\t\treturn nil, fmt.Errorf(\"bad legacy ss hp\")\n\t}\n\thost := hp[:colon]\n\tport, err := strconv.Atoi(hp[colon+1:])\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"bad legacy ss port %q: %w\", hp[colon+1:], err)\n\t}\n\tmethod, pass := splitMethodPass(userInfo)\n\tidentity := \"ss:\" + method + \":\" + pass + \"@\" + host + \":\" + strconv.Itoa(port)\n\tob := Outbound{\n\t\t\"protocol\": \"shadowsocks\",\n\t\t\"tag\":      remark,\n\t\t\"settings\": map[string]any{\n\t\t\t\"servers\": []any{\n\t\t\t\tmap[string]any{\"address\": host, \"port\": port, \"password\": pass, \"method\": method},\n\t\t\t},\n\t\t},\n\t}\n\treturn &ParseResult{Outbound: ob, Identity: identity}, nil","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/util/link/outbound.go#L380-L416","documentation":"Returned by the legacy ss branch when the base64-decoded payload does contain an '@', but the host:port part after it has no ':' (LastIndex returns -1). The parser now has a host but no way to extract a port, so it refuses rather than inventing one.","triggerScenarios":"Decoded payload like 'method:pass@host' (port omitted); truncation that cut ':port'; IPv6 host without brackets so parsing logic still finds no usable colon; whitespace or encoding artifacts swallowing the tail.","commonSituations":"Hand-built legacy links where the port was forgotten; partially corrupted subscriptions; providers testing with dummy entries.","solutions":["Decode and inspect the payload; append the missing ':port' and re-encode.","Use the SIP002 form going forward — it keeps host and port in clear text and fails more obviously.","Validate legacy payloads with a regexp like ^[^@]+@[^@]+:\\d+$ before parsing in bulk."],"exampleFix":"// before (payload decodes to aes-256-gcm:pass@example.com)\nss://YWVzLTI1Ni1nY206cGFzc0BleGFtcGxlLmNvbQ==\n\n// after (port appended)\nss://YWVzLTI1Ni1nY206cGFzc0BleGFtcGxlLmNvbTo0NDM=","handlingStrategy":"validation","validationCode":"var legacySSRe = regexp.MustCompile(`^[^@]+@[^@]+:\\d{1,5}$`)\nfunc validLegacySSPayload(link string) bool {\n    core := strings.TrimPrefix(link, \"ss://\")\n    dec, err := base64DecodeFlexible(core)\n    return err == nil && legacySSRe.MatchString(dec)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always append ':port' in legacy ss payloads.","Migrate links to SIP002 where the port is human-readable.","Reject port-less entries at import time."],"tags":["parsing","proxy-links","shadowsocks","legacy","port"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}