invoke-ai/InvokeAI · error · ValueError
Failed to create user: {e}
Error message
Failed to create user: {e} What it means
UserService._create wraps sqlite3.IntegrityError raised by the INSERT into the users table as a ValueError. This means the new user row violated a database constraint - almost always the UNIQUE constraint on email (or user_id), or a NOT NULL constraint. The original sqlite message is preserved in the exception text and __cause__.
Source
Thrown at invokeai/app/services/users/users_default.py:117
# before the INSERT below commits. In-process callers are additionally
# serialized by the database's shared RLock; the explicit lock also covers a
# second process (invoke-useradd --admin) writing during the setup window.
cursor.execute("BEGIN IMMEDIATE")
# Same predicate as has_admin(), read on the cursor that performs the write.
cursor.execute("SELECT COUNT(*) FROM users WHERE is_admin = TRUE AND is_active = TRUE")
row = cursor.fetchone()
if row and row[0] > 0:
raise ValueError("Admin user already exists")
try:
cursor.execute(
"""
INSERT INTO users (user_id, email, display_name, password_hash, is_admin)
VALUES (?, ?, ?, ?, ?)
""",
(user_id, user_data.email, user_data.display_name, password_hash, user_data.is_admin),
)
except sqlite3.IntegrityError as e:
raise ValueError(f"Failed to create user: {e}") from e
user = self.get(user_id)
if user is None:
raise RuntimeError("Failed to retrieve created user")
return user
def get(self, user_id: str) -> UserDTO | None:
"""Get user by ID."""
with self._db.transaction() as cursor:
cursor.execute(
f"""
SELECT {_USER_DTO_COLUMNS}
FROM users
WHERE user_id = ?
""",
(user_id,),
)
row = cursor.fetchone()View on GitHub (pinned to 0b6a024f2f)
Solutions
- Check whether the email already exists (self.get_by_email or SELECT) before calling create, or treat ValueError as 'already exists'.
- Read the wrapped sqlite3 message (e.__cause__) to see which constraint failed (users.email UNIQUE vs NOT NULL).
- Use a different email/user_id for the new account, or update the existing user instead of creating a new one.
- Wrap the create call in a try/except sqlite3.IntegrityError at the call site if duplicates are expected and should be idempotent.
Example fix
// before
user = users.create(UserCreateRequest(email='admin@example.com', ...))
// after
try:
user = users.create(UserCreateRequest(email='admin@example.com', ...))
except ValueError as e:
user = users.get_by_email('admin@example.com') # already registered Defensive patterns
Strategy: validation
Validate before calling
if users.get_by_email(req.email) is not None:
raise ValueError(f'Email {req.email} already registered') Try / catch
try:
user = users.create(req)
except ValueError as e:
if 'UNIQUE' in str(e):
user = users.get_by_email(req.email)
else:
raise Prevention
- Check for an existing email before creating; treat duplicates as updates, not inserts
- Make bootstrap scripts idempotent (create only if get_by_email returns None)
- Catch and inspect the wrapped sqlite3.IntegrityError (__cause__) to identify the failing constraint
- Normalize emails (lowercase, trim) before insert to avoid case-variant duplicates
When it happens
Trigger: Calling UserService.create(...) or create_admin(...) with a UserCreateRequest whose email (or generated user_id) already exists in the users table, or with a field that violates a NOT NULL constraint on the users table.
Common situations: Re-running an initialization/bootstrap script that registers a default admin; a race where two workers insert the same email; case-variant duplicate emails ('Admin@x.com' vs 'admin@x.com') colliding with a case-insensitive unique index; an email column added later with UNIQUE that existing data now violates.
Related errors
- A model with path '{config.path}' is already installed
- Invalid or expired token
- User not found or inactive
- Missing authentication credentials
- Invalid or expired authentication token
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/c996bbce97a5d58f.
Report an issue: GitHub.