{"record":{"id":"449c3d4d79107c71","repo":"plandex-ai/plandex","slug":"invalid-email","errorCode":null,"errorMessage":"Invalid email: ","messagePattern":"Invalid email: ","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"app/server/handlers/invites.go","lineNumber":78,"sourceCode":"\t\thttp.Error(w, \"Error unmarshalling request: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\treq.Email = strings.ToLower(req.Email)\n\n\t// ensure current user can invite target user\n\tpermission := shared.Permission(strings.Join([]string{string(shared.PermissionInviteUser), req.OrgRoleId}, \"|\"))\n\n\tif !auth.HasPermission(permission) {\n\t\tlog.Printf(\"User does not have permission to invite user with role: %v\\n\", req.OrgRoleId)\n\t\thttp.Error(w, \"User does not have permission to invite user with role: \"+req.OrgRoleId, http.StatusForbidden)\n\t\treturn\n\t}\n\n\t// ensure user doesn't already have access to org via domain\n\tsplit := strings.Split(req.Email, \"@\")\n\tif len(split) != 2 {\n\t\tlog.Printf(\"Invalid email: %v\\n\", req.Email)\n\t\thttp.Error(w, \"Invalid email: \"+req.Email, http.StatusBadRequest)\n\t\treturn\n\t}\n\tdomain := &split[1]\n\n\tif org.AutoAddDomainUsers && org.Domain == domain {\n\t\tlog.Printf(\"User already has access to org via domain: %v\\n\", domain)\n\t\thttp.Error(w, \"User already has access to org via domain: \"+*domain, http.StatusBadRequest)\n\t}\n\n\t// ensure user with this email isn't already in the org\n\tuser, err := db.GetUserByEmail(req.Email)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error getting user: %v\\n\", err)\n\t\thttp.Error(w, \"Error getting user: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/invites.go#L60-L96","documentation":"The handler validates the invitee email by splitting on '@' and requiring exactly two parts. If the email doesn't contain exactly one '@', it responds 400 with 'Invalid email: <email>'. Validation is deliberately minimal — it only checks the @ shape, not full RFC 5322 validity.","triggerScenarios":"Submitting an invite with an email missing '@' ('userexample.com'), containing multiple '@' ('a@@b.com' or 'a@b@c.com'), an empty string, or whitespace/garbage typed into an invite form or CLI flag.","commonSituations":"Typos when entering an email; shell scripts passing unquoted/empty variables into a curl payload; copying emails with surrounding spaces or encoded characters; programmatic callers forgetting to trim or normalize input (the server lowercases but does not trim).","solutions":["Validate the email client-side before calling the API — require a single '@' with non-empty local and domain parts","Trim whitespace and lowercase the email before sending; re-check for accidental empty values","Fix any shell/script quoting so the email variable is actually populated in the JSON body","For stricter checking, apply a proper email regex on the client before making the request"],"exampleFix":"// before\nemail=\"dev@@example.com\"\n// after\nemail=$(echo \" dev@example.com \" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')\necho \"$email\" | grep -Eq '^[^@]+@[^@]+$' || { echo \"invalid email\"; exit 1; }","handlingStrategy":"validation","validationCode":"// Validate the email shape before calling the invite API\nvar emailRe = regexp.MustCompile(`^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$`)\nfunc validEmail(s string) bool {\n    s = strings.ToLower(strings.TrimSpace(s))\n    return emailRe.MatchString(s)\n}\nif !validEmail(email) {\n    return fmt.Errorf(\"invalid email %q — must contain exactly one @\", email)\n}","typeGuard":"func isWellFormedEmail(s string) bool {\n    return strings.Count(strings.TrimSpace(s), \"@\") == 1 &&\n        len(strings.TrimSpace(s)) > 0\n}","tryCatchPattern":"err := client.InviteUser(ctx, email, roleID)\nif err != nil && strings.Contains(err.Error(), \"Invalid email\") {\n    return fmt.Errorf(\"server rejected email %q — check for typos, extra @, or whitespace\", email)\n}","preventionTips":["Run a regex email check client-side before every invite call","Trim and lowercase emails before sending (server lowercases but does not trim)","Quote variables in shell scripts so empty values can't slip through","Never send raw user-typed input without normalization"],"tags":["validation","email","http","input"],"backgroundTag":"invalid-email-format","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}