{"record":{"id":"3b68f7418befcf15","repo":"MHSanaei/3x-ui","slug":"wireguard-publickey-w","errorCode":null,"errorMessage":"wireguard publicKey: %w","messagePattern":"wireguard publicKey: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xray/api.go","lineNumber":630,"sourceCode":"\t\t\tCipherType: ssCipherType,\n\t\t}), nil\n\tcase \"hysteria\":\n\t\tauth, err := getRequiredUserString(user, \"auth\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\treturn serial.ToTypedMessage(&hysteriaAccount.Account{\n\t\t\tAuth: auth,\n\t\t}), nil\n\tcase \"wireguard\":\n\t\tpubB64, err := getRequiredUserString(user, \"publicKey\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpubHex, err := wgutil.KeyToHex(pubB64)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"wireguard publicKey: %w\", err)\n\t\t}\n\n\t\tpskB64, err := getOptionalUserString(user, \"preSharedKey\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpskHex, err := wgutil.KeyToHex(pskB64)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"wireguard preSharedKey: %w\", err)\n\t\t}\n\n\t\tallowed := collectStringSlice(user[\"allowedIPs\"])\n\t\tif len(allowed) == 0 {\n\t\t\treturn nil, common.NewError(\"wireguard: allowedIPs required\")\n\t\t}\n\n\t\tkeepAlive, err := getOptionalUserString(user, \"keepAlive\")\n\t\tif err != nil {","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/xray/api.go#L612-L648","documentation":"Wireguard branch of the Xray account builder: the required 'publicKey' passed the presence check but wgutil.KeyToHex rejected it. KeyToHex base64-decodes the value and expects exactly the 32-byte Wireguard key length, so this wraps either a base64 decode error or a wrong-length error — the publicKey is not a valid Wireguard public key.","triggerScenarios":"Providing a wireguard client publicKey that is: hex instead of base64 (Wireguard tools often print hex), a base64 string of the wrong length, a private key pasted by mistake, or a key with whitespace/typo corruption.","commonSituations":"Copy-paste from 'wg show' output (hex form) into a field expecting base64; mixing up private/public keys when creating a peer; truncated keys from terminal copy; keys generated by a non-standard tool.","solutions":["Regenerate the keypair and paste the base64 (base64nopad) form of the PUBLIC key — 'wg pubkey' output or 'wg genkey | wg pubkey' is the canonical source; Xray expects the same 32-byte base64 form as wireguard-go.","Verify length: base64 of 32 bytes is 43 chars without padding (44 with '='). A 64-char hex string means you copied hex — convert it (echo <hex> | xxd -r -p | base64) or re-derive from the tool.","Ensure no leading/trailing whitespace or quotes snuck into the stored value."],"exampleFix":"// before — hex form pasted\nuser[\"publicKey\"] = \"8f4a1c...\" // 64 hex chars\n\n// after — base64 (43-44 chars) form\nuser[\"publicKey\"] = \"j0ocQKx+Zr1f3...\" // base64 of the same 32 bytes","handlingStrategy":"validation","validationCode":"// Validate a Wireguard key (base64, 32 bytes) before it reaches Xray\nfunc isValidWGKeyB64(s string) bool {\n    s = strings.TrimSpace(s)\n    if len(s) == 44 && strings.HasSuffix(s, \"=\") {\n        s = s[:43]\n    }\n    if len(s) != 43 {\n        return false\n    }\n    raw, err := base64.RawStdEncoding.DecodeString(s)\n    return err == nil && len(raw) == 32\n}","typeGuard":"null","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"wireguard publicKey\") {\n    // regenerate via `wg genkey | wg pubkey`, paste base64 form; no retry\n}","preventionTips":["Generate keys with wg genkey/wg pubkey and copy the base64 output verbatim.","Sanity-check length (43-44 base64 chars) at paste time in the UI."],"tags":["wireguard","xray","crypto","validation"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}