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

  1. Check whether the email already exists (self.get_by_email or SELECT) before calling create, or treat ValueError as 'already exists'.
  2. Read the wrapped sqlite3 message (e.__cause__) to see which constraint failed (users.email UNIQUE vs NOT NULL).
  3. Use a different email/user_id for the new account, or update the existing user instead of creating a new one.
  4. 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

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


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/c996bbce97a5d58f. Report an issue: GitHub.