MHSanaei/3x-ui · warning
vmess decode: %w
Error message
vmess decode: %w
What it means
Returned by parseVmess when the base64 payload after vmess:// decodes with neither padded StdEncoding nor RawURLEncoding. VMess share links carry base64(JSON); providers emit at least three variants (padded, unpadded, URL-safe), and this parser tries both before giving up. Everything before the JSON stage, so no protocol state is involved.
Source
Thrown at internal/util/link/outbound.go:142
case strings.HasPrefix(link, "wireguard://"), strings.HasPrefix(link, "wg://"):
return parseWireguard(link)
default:
return nil, fmt.Errorf("unsupported link scheme")
}
}
// --- vmess ---
func parseVmess(link string) (*ParseResult, error) {
b64 := strings.TrimPrefix(link, "vmess://")
// vmess:// base64(json)
raw, err := base64.StdEncoding.DecodeString(padBase64(b64))
if err != nil {
// Some providers use raw URL-safe
raw, err = base64.RawURLEncoding.DecodeString(b64)
}
if err != nil {
return nil, fmt.Errorf("vmess decode: %w", err)
}
var j map[string]any
if err := json.Unmarshal(raw, &j); err != nil {
return nil, fmt.Errorf("vmess json: %w", err)
}
identity := vmessIdentity(j)
network := getString(j, "net", "tcp")
security := "none"
if tls, _ := j["tls"].(string); tls == "tls" {
security = "tls"
}
stream := buildStream(network, security)
// Map known fields (best effort, matching frontend parser coverage)
switch network {
case "ws":View on GitHub (pinned to ad32144c42)
Solutions
- Re-copy the full link from the source client and check it was not truncated (vmess payloads are long).
- Validate the payload yourself: strip 'vmess://', then try base64.RawURLEncoding and base64.StdEncoding with padding restored — if both fail, the payload is not base64 at all.
- If the payload is raw JSON, re-encode it to base64 or parse the JSON directly.
- Regenerate the link from the originating client rather than hand-repairing it.
Example fix
// before
raw, err := base64.StdEncoding.DecodeString(b64)
// after: tolerate all three common vmess encodings
s := strings.Map(func(r rune) rune {
if r == '\n' || r == '\r' || r == ' ' { return -1 }
return r
}, b64)
raw, err := base64.StdEncoding.DecodeString(padBase64(s))
if err != nil {
raw, err = base64.RawURLEncoding.DecodeString(s)
} Defensive patterns
Strategy: validation
Validate before calling
func isBase64ishPayload(link string) bool {
s := strings.TrimPrefix(link, "vmess://")
s = strings.Map(func(r rune) rune {
if r == '\n' || r == '\r' || r == ' ' { return -1 }
return r
}, s)
_, err1 := base64.StdEncoding.DecodeString(padBase64(s))
_, err2 := base64.RawURLEncoding.DecodeString(s)
return err1 == nil || err2 == nil
} Try / catch
if _, err := link.ParseOutbound(l); err != nil {
if strings.Contains(err.Error(), "vmess decode") {
// payload is not base64: log the link, skip it, request a fresh copy from the provider
}
} Prevention
- Copy vmess links whole — they are long and truncate easily.
- Strip whitespace/newlines from payloads before parsing.
- Reject links whose payload is plain JSON (not base64).
When it happens
Trigger: A vmess:// link whose payload is plain JSON (not base64); payload corrupted by URL-transport (spaces, +→%2B mishandling); missing padding combined with -/_ mixed into a single string; copy-paste truncation cutting the payload mid-base64.
Common situations: Links copied out of messengers/webpages where the base64 got percent-decoded or truncated; providers emitting base64 with newlines; homegrown generators that forget padding AND use URL-safe alphabet while the parser only tolerates one deviation at a time.
Related errors
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/e5d8ce4cbbf17722.
Report an issue: GitHub.