{"record":{"id":"c8121963f5ccb3c5","repo":"MHSanaei/3x-ui","slug":"base64-decode-failed","errorCode":null,"errorMessage":"base64 decode failed","messagePattern":"base64 decode failed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/util/link/outbound.go","lineNumber":954,"sourceCode":"\treturn splitComma(s)\n}\n\nfunc padBase64(s string) string {\n\tfor len(s)%4 != 0 {\n\t\ts += \"=\"\n\t}\n\treturn s\n}\n\nfunc base64DecodeFlexible(s string) (string, error) {\n\ts = padBase64(s)\n\tif b, err := base64.StdEncoding.DecodeString(s); err == nil {\n\t\treturn string(b), nil\n\t}\n\tif b, err := base64.RawURLEncoding.DecodeString(strings.TrimRight(s, \"=\")); err == nil {\n\t\treturn string(b), nil\n\t}\n\treturn \"\", fmt.Errorf(\"base64 decode failed\")\n}\n\n// SlugRemark turns a free-form remark into a tag segment, keeping Unicode\n// letters and digits (so non-ASCII remarks like Cyrillic stay readable) and\n// replacing every other run of characters with a single dash.\nvar slugRe = regexp.MustCompile(`[^\\p{L}\\p{N}]+`)\n\nfunc SlugRemark(remark string) string {\n\ts := strings.ToLower(strings.TrimSpace(remark))\n\ts = slugRe.ReplaceAllString(s, \"-\")\n\ts = strings.Trim(s, \"-\")\n\tif s == \"\" {\n\t\treturn \"\"\n\t}\n\t// collapse runs of dashes\n\tfor strings.Contains(s, \"--\") {\n\t\ts = strings.ReplaceAll(s, \"--\", \"-\")\n\t}","sourceCodeStart":936,"sourceCodeEnd":972,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/util/link/outbound.go#L936-L972","documentation":"base64DecodeFlexible tries standard-padded base64 first, then raw URL-safe base64 (with padding stripped); if both decoders reject the input it returns 'base64 decode failed'. It exists to accept the many base64 variants found in share links (padded/unpadded, standard/URL-safe alphabets). Reaching this error means the input is not valid base64 in either alphabet — usually because the payload is plain text, HTML, or truncated.","triggerScenarios":"Decoding the userinfo segment of vmess:// links, the base64 body of ss:// links, or base64 subscription bodies where the string contains characters outside both alphabets (e.g. '-', '_' mixed with '+', '/', or non-ASCII), has internal whitespace, or was cut mid-encoding.","commonSituations":"A subscription URL returns an HTML error page (Cloudflare challenge, 404 page) that then gets base64-decoded as if it were a subscription; copy-paste of a link losing trailing characters; double-encoding mismatches; payloads already URL-unescaped incorrectly so '%' remains.","solutions":["Print/inspect the offending string — if it starts with '<' or readable text, your source is not base64 (fetch error page, wrong Content-Type handling).","Strip whitespace and newlines before decoding: strings.Map to remove \\n, \\r, spaces.","Ensure the string was URL-unescaped exactly once before decoding.","If you control the producer, emit standard base64 with padding or raw URL-safe base64 consistently."],"exampleFix":"// before\ndecoded, err := base64DecodeFlexible(payload) // payload has \\n inside\n\n// after\npayload = strings.NewReplacer(\"\\n\", \"\", \"\\r\", \"\", \" \", \"\").Replace(payload)\ndecoded, err := base64DecodeFlexible(payload)","handlingStrategy":"validation","validationCode":"func looksLikeBase64(s string) bool {\n\ts = strings.NewReplacer(\"\\n\", \"\", \"\\r\", \"\", \" \", \"\").Replace(s)\n\tif len(s) == 0 { return false }\n\tfor _, r := range s {\n\t\tif !(r >= 'A' && r <= 'Z' || r >= 'a' && r <= 'z' || r >= '0' && r <= '9' || r == '+' || r == '/' || r == '-' || r == '_' || r == '=') {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}","typeGuard":null,"tryCatchPattern":"decoded, err := base64DecodeFlexible(payload)\nif err != nil {\n    return fmt.Errorf(\"subscription payload not base64 (likely HTML/text, got %q...): %w\", payload[:min(40, len(payload))], err)\n}","preventionTips":["Check the HTTP Content-Type and first byte of subscription responses before base64-decoding.","Strip whitespace/newlines from pasted base64 before decoding.","URL-unescape exactly once before decoding."],"tags":["base64","config-parsing","subscription","encoding"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}