langflow-ai/langflow · warning · HTTPException

Role not found

Error message

Role not found

What it means

Raised by GET /api/v1/authz/roles/{role_id} when the id does not match any AuthzRole row. Unlike the mutation routes this read is available to any authenticated user, and returns HTTP 404 'Role not found' with no body leak beyond the message.

Source

Thrown at src/backend/base/langflow/api/v1/authz_roles.py:101

    stmt = select(AuthzRole)
    if is_system is not None:
        stmt = stmt.where(AuthzRole.is_system == is_system)
    if name:
        stmt = stmt.where(AuthzRole.name.ilike(f"%{escape_like_pattern(name)}%", escape="\\"))
    stmt = stmt.order_by(AuthzRole.name, AuthzRole.id).offset(offset).limit(limit)
    rows = (await session.exec(stmt)).all()
    return [RoleRead.model_validate(row) for row in rows]


@router.get("/{role_id}", response_model=RoleRead)
async def read_role(
    role_id: UUID,
    session: DbSession,
    current_user: CurrentActiveUser,  # noqa: ARG001 — any authenticated user can read
) -> RoleRead:
    role = await session.get(AuthzRole, role_id)
    if role is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Role not found")
    return RoleRead.model_validate(role)


@router.post("", response_model=RoleRead, status_code=status.HTTP_201_CREATED)
@router.post("/", response_model=RoleRead, status_code=status.HTTP_201_CREATED)
async def create_role(
    payload: RoleCreate,
    current_user: CurrentActiveUser,
    session: DbSession,
) -> RoleRead:
    """Create a custom (non-system) role. Superuser-only."""
    _require_superuser(current_user)

    if payload.parent_role_id is not None:
        parent = await session.get(AuthzRole, payload.parent_role_id)
        if parent is None:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Handle 404 by redirecting to the roles list and clearing stale cached ids
  2. Resolve roles by name via the list endpoint instead of persisting ids
  3. Confirm the environment/DB the client targets
Defensive patterns

Strategy: try-catch

Validate before calling

const roles = await api.get('/api/v1/authz/roles');
if (!roles.some(r => r.id === roleId)) throw new Error('role not found');

Type guard

const isUuid = (v: string): boolean =>
  /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);

Try / catch

catch (e) { if (e.status === 404) { clearCachedRole(roleId); navigate('/authz/roles'); } }

Prevention

When it happens

Trigger: GET a role id that was deleted, a UUID typo, or an id from another environment/installation where the role table was seeded differently.

Common situations: Deep links to a role detail page that outlived the role, cached role ids in frontend state after an admin deletes roles, or cross-environment id copying.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/a3e4077105a1b171. Report an issue: GitHub.