plandex-ai/plandex · warning

Invalid email:

Error message

Invalid email: 

What it means

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.

Source

Thrown at app/server/handlers/invites.go:78

		http.Error(w, "Error unmarshalling request: "+err.Error(), http.StatusInternalServerError)
		return
	}
	req.Email = strings.ToLower(req.Email)

	// ensure current user can invite target user
	permission := shared.Permission(strings.Join([]string{string(shared.PermissionInviteUser), req.OrgRoleId}, "|"))

	if !auth.HasPermission(permission) {
		log.Printf("User does not have permission to invite user with role: %v\n", req.OrgRoleId)
		http.Error(w, "User does not have permission to invite user with role: "+req.OrgRoleId, http.StatusForbidden)
		return
	}

	// ensure user doesn't already have access to org via domain
	split := strings.Split(req.Email, "@")
	if len(split) != 2 {
		log.Printf("Invalid email: %v\n", req.Email)
		http.Error(w, "Invalid email: "+req.Email, http.StatusBadRequest)
		return
	}
	domain := &split[1]

	if org.AutoAddDomainUsers && org.Domain == domain {
		log.Printf("User already has access to org via domain: %v\n", domain)
		http.Error(w, "User already has access to org via domain: "+*domain, http.StatusBadRequest)
	}

	// ensure user with this email isn't already in the org
	user, err := db.GetUserByEmail(req.Email)

	if err != nil {
		log.Printf("Error getting user: %v\n", err)
		http.Error(w, "Error getting user: "+err.Error(), http.StatusInternalServerError)
		return
	}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Validate the email client-side before calling the API — require a single '@' with non-empty local and domain parts
  2. Trim whitespace and lowercase the email before sending; re-check for accidental empty values
  3. Fix any shell/script quoting so the email variable is actually populated in the JSON body
  4. For stricter checking, apply a proper email regex on the client before making the request

Example fix

// before
email="dev@@example.com"
// after
email=$(echo " dev@example.com " | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
echo "$email" | grep -Eq '^[^@]+@[^@]+$' || { echo "invalid email"; exit 1; }
Defensive patterns

Strategy: validation

Validate before calling

// Validate the email shape before calling the invite API
var emailRe = regexp.MustCompile(`^[^@\s]+@[^@\s]+\.[^@\s]+$`)
func validEmail(s string) bool {
    s = strings.ToLower(strings.TrimSpace(s))
    return emailRe.MatchString(s)
}
if !validEmail(email) {
    return fmt.Errorf("invalid email %q — must contain exactly one @", email)
}

Type guard

func isWellFormedEmail(s string) bool {
    return strings.Count(strings.TrimSpace(s), "@") == 1 &&
        len(strings.TrimSpace(s)) > 0
}

Try / catch

err := client.InviteUser(ctx, email, roleID)
if err != nil && strings.Contains(err.Error(), "Invalid email") {
    return fmt.Errorf("server rejected email %q — check for typos, extra @, or whitespace", email)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/449c3d4d79107c71. Report an issue: GitHub.