infiniflow/ragflow · error · AdminException
Invalid email address: {username}!
Error message
Invalid email address: {username}! What it means
Raised by UserMgr.create_user (admin/server/services.py:85) as an AdminException (HTTP 400) when the supplied username fails the email regex ^[\w\._-]+@([\w_-]+\.)+[\w-]{2,}$. The admin user-management API only accepts users identified by email address, so a malformed address is rejected before any database lookup. The message embeds the offending username verbatim.
Source
Thrown at admin/server/services.py:85
"email": user.email,
"language": user.language,
"last_login_time": user.last_login_time,
"is_active": user.is_active,
"is_anonymous": user.is_anonymous,
"login_channel": user.login_channel,
"status": user.status,
"is_superuser": user.is_superuser,
"create_date": user.create_date,
"update_date": user.update_date,
}
)
return result
@staticmethod
def create_user(username, password, role="user") -> dict:
# Validate the email address
if not re.match(r"^[\w\._-]+@([\w_-]+\.)+[\w-]{2,}$", username):
raise AdminException(f"Invalid email address: {username}!")
# Check if the email address is already used
if UserService.query(email=username):
raise UserAlreadyExistsError(username)
# Construct user info data
user_info_dict = {
"email": username,
"nickname": "", # ask user to edit it manually in settings.
"password": decrypt(password),
"login_channel": "password",
"is_superuser": role == "admin",
}
return create_new_user(user_info_dict)
@staticmethod
def delete_user(username):
# use email to delete
user_list = UserService.query_user_by_email(username)
if not user_list:View on GitHub (pinned to 554fb1133a)
Solutions
- Pass a well-formed email address as username, e.g. 'user@example.com' (needs a dotted domain of 2+ letters).
- Strip/trim whitespace from the username before calling create_user.
- If you need '+' addressing, pre-validate and normalize the address (e.g. strip the +tag part) or relax the regex in services.py to accept it.
- Add client-side email format validation before invoking the admin API so users get feedback early.
Example fix
# before
UserMgr.create_user('user+tag@example.com', encrypted_pw) # raises Invalid email address
# after
import re
email = 'user+tag@example.com'.strip()
assert re.match(r"^[\w\._-]+@([\w_-]+\.)+[\w-]{2,}$", email), 'address rejected by admin API'
UserMgr.create_user(email.split('+')[0] + '@example.com', encrypted_pw) Defensive patterns
Strategy: validation
Validate before calling
import re
EMAIL_RE = re.compile(r"^[\w\._-]+@([\w_-]+\.)+[\w-]{2,}$")
def is_valid_admin_email(username: str) -> bool:
return bool(username and EMAIL_RE.match(username.strip())) Type guard
def is_valid_admin_email(username: str) -> bool:
import re
return isinstance(username, str) and bool(re.match(r"^[\w\._-]+@([\w_-]+\.)+[\w-]{2,}$", username.strip())) Try / catch
from admin.server.exceptions import AdminException
try:
UserMgr.create_user(email, encrypted_pw, role)
except AdminException as e:
if e.code == 400 and e.message.startswith('Invalid email address'):
raise ValueError(f'bad email input: {email!r}') from e
raise Prevention
- Validate the email against the same regex the server uses before calling create_user.
- Strip whitespace and lowercase the address client-side.
- Reject '+'-style addresses or normalize them before submission; this regex does not accept them.
- Surface server 400 messages to the operator verbatim in provisioning scripts.
When it happens
Trigger: POST to the admin CLI/server 'create user' endpoint with a non-email username: missing '@', no dot in the domain, a single-label domain ('user@localhost'), or characters outside [A-Za-z0-9_.-] such as 'user+tag@example.com' (the '+' is rejected by this regex).
Common situations: Scripts that pass a nickname or phone-style id instead of an email; plus-addressed addresses; IDN/unicode emails; leading/trailing whitespace in shell arguments; typos in automation config files feeding the admin command.
Related errors
- User '{username}' already exists
- User '{username}' not found
- Invalid activate_status: {activate_status}
- 404
- main() must be defined or exported.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/daeb79a56e68c368.
Report an issue: GitHub.