langflow-ai/langflow · warning · HTTPException
System roles cannot be modified
Error message
System roles cannot be modified
What it means
Raised by PATCH /api/v1/authz/roles/{role_id} when the target role has is_system=True. System roles (the seeded viewer/developer/admin catalog) are read-only; the route rejects any modification with HTTP 400 'System roles cannot be modified'.
Source
Thrown at src/backend/base/langflow/api/v1/authz_roles.py:171
logger.info("Created role %s (id=%s)", role.name, role.id)
return RoleRead.model_validate(role)
@router.patch("/{role_id}", response_model=RoleRead)
async def update_role(
role_id: UUID,
payload: RoleUpdate,
current_user: CurrentActiveUser,
session: DbSession,
) -> RoleRead:
"""Update fields on a custom role. System roles are read-only."""
_require_superuser(current_user)
role = await session.get(AuthzRole, role_id)
if role is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Role not found")
if role.is_system:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="System roles cannot be modified",
)
# Use presence checks (model_fields_set) rather than ``is not None`` so PATCH
# can clear nullable fields. An explicit ``"description": null`` in the body
# marks the field as set and assigns None; omitting it leaves the row alone.
fields_set = payload.model_fields_set
if "parent_role_id" in fields_set:
if payload.parent_role_id is None:
role.parent_role_id = None
else:
if payload.parent_role_id == role.id:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="A role cannot be its own parent",
)View on GitHub (pinned to 976ec789d2)
Solutions
- Create a custom role with parent_role_id pointing at the system role and set permissions on the child
- Assign the custom role to users instead of mutating the system role
- Filter out is_system roles in admin UI edit actions
- Make provisioning scripts skip rows where is_system is true
Example fix
// before
await api.patch(`/authz/roles/${devRoleId}`, { permissions: ['flow:deploy'] });
// after
await api.post('/authz/roles', { name: 'deployer', parent_role_id: devRoleId, permissions: ['flow:deploy'] });
// then assign 'deployer' to users Defensive patterns
Strategy: validation
Validate before calling
const role = await api.get(`/authz/roles/${id}`);
if (role.is_system) throw new Error('system roles are read-only; create a child role instead'); Type guard
const isModifiableRole = (r: { is_system: boolean }): boolean => !r.is_system; Try / catch
catch (e) { if (e.status === 400) offerCreateChildRole(roleId, patch); } Prevention
- Model customizations as child roles with parent_role_id inheritance, never edits to system roles
- Filter is_system roles out of editable admin UI actions
- Provisioning scripts must skip is_system rows
When it happens
Trigger: PATCH /api/v1/authz/roles/{id} for one of the three system-seeded roles — attempting to rename it, change permissions, repoint its parent, or clear its description. Any field in RoleUpdate triggers the check.
Common situations: Admins trying to tweak the built-in role catalog instead of creating a derived custom role (using parent_role_id to inherit), or provisioning scripts that 'ensure permissions' on every role including system ones.
Related errors
- parent_role_id does not reference an existing role
- A role cannot be its own parent
- Setting this parent would create a role hierarchy cycle
- Superuser required to administer roles.
- Role not found
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/d7968a0760a04a45.
Report an issue: GitHub.