HKUDS/DeepTutor · error · ValueError

Invalid role: {role!r}. Must be 'admin' or 'user'.

Error message

Invalid role: {role!r}. Must be 'admin' or 'user'.

What it means

set_role in deeptutor.services.auth only accepts the two literal roles 'admin' and 'user'; any other string raises ValueError. It is a public wrapper around the multi-user identity store's set_role.

Source

Thrown at deeptutor/services/auth.py:182

    Remove a user from the store. Returns True if the user existed.

    """
    from deeptutor.multi_user.identity import delete_user as _delete_user

    if not _delete_user(username):
        return False
    logger.info("User '%s' deleted", username)
    return True


def set_role(username: str, role: str) -> bool:
    """
    Change the role for an existing user. Returns True on success.

    Valid roles: 'admin', 'user'.
    """
    if role not in ("admin", "user"):
        raise ValueError(f"Invalid role: {role!r}. Must be 'admin' or 'user'.")

    from deeptutor.multi_user.identity import set_role as _set_role

    if not _set_role(username, role):  # type: ignore[arg-type]
        return False
    logger.info(f"User '{username}' role updated to {role!r}")
    return True


def set_avatar(username: str, avatar: str) -> bool:
    """
    Update the avatar marker for an existing user. Returns True on success.

    The marker is either '' (deterministic fallback), 'icon:<name>:<color>',
    or 'img:<version>' (managed by the avatar upload endpoint).
    """
    from deeptutor.multi_user.identity import set_avatar as _set_avatar

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Use exactly 'admin' or 'user' (lowercase)
  2. Strip/normalize input: role.strip().lower() before calling
  3. If loading roles from config, validate against ('admin','user') at load time and fail fast with a clear config error

Example fix

# before
set_role("alice", "Admin")
# after
set_role("alice", "admin")
Defensive patterns

Strategy: validation

Validate before calling

VALID_ROLES = ("admin", "user")
role = role.strip().lower() if isinstance(role, str) else role
if role not in VALID_ROLES:
    raise ValueError(f"role must be one of {VALID_ROLES}")
set_role(username, role)

Type guard

from typing import Literal
Role = Literal["admin", "user"]
def is_role(value: str) -> TypeGuard[Role]:
    return value in ("admin", "user")

Try / catch

try:
    set_role(user, role)
except ValueError as e:
    if "Invalid role" in str(e):
        role = role.strip().lower()
        set_role(user, role) if is_role(role) else fail()

Prevention

When it happens

Trigger: Calling auth.set_role(username, role) with values like 'superuser', 'moderator', 'ADMIN' (case matters), or an empty string.

Common situations: Scripts promoting users assuming roles like 'root' or 'owner' exist; case-sensitivity bugs ('Admin'); role strings loaded from a config/env var with trailing whitespace; enum drift after role vocabulary changes upstream.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/1ca7565af74c8b03. Report an issue: GitHub.