{"record":{"id":"2e7dc0e0e4979454","repo":"langflow-ai/langflow","slug":"name-conflict-another-role-already-uses-this-nam","errorCode":null,"errorMessage":"Name conflict — another role already uses this name","messagePattern":"Name conflict — another role already uses this name","errorType":"http","errorClass":"HTTPException","httpStatus":409,"severity":"error","filePath":"src/backend/base/langflow/api/v1/authz_roles.py","lineNumber":235,"sourceCode":"\n    if \"permissions\" in fields_set:\n        # permissions column is nullable=False (default_factory=list). An empty\n        # list is the natural \"clear\" — None would violate the constraint at\n        # commit, so reject it up front.\n        if payload.permissions is None:\n            raise HTTPException(\n                status_code=status.HTTP_400_BAD_REQUEST,\n                detail=\"permissions cannot be null; pass an empty list to clear\",\n            )\n        role.permissions = list(payload.permissions)\n\n    role.updated_at = datetime.now(timezone.utc)\n\n    try:\n        await session.commit()\n    except IntegrityError as exc:\n        await session.rollback()\n        raise HTTPException(\n            status_code=status.HTTP_409_CONFLICT,\n            detail=\"Name conflict — another role already uses this name\",\n        ) from exc\n    await session.refresh(role)\n    await safe_invalidate_role(get_authorization_service(), role.id, op=\"role:update\")\n    await audit_decision(\n        user_id=current_user.id,\n        action=\"role:update\",\n        obj=f\"role:{role.id}\",\n        result=\"allow\",\n        details={\n            \"role_name\": role.name,\n            \"fields_changed\": sorted(fields_set),\n        },\n    )\n    logger.info(\"Updated role %s (id=%s)\", role.name, role.id)\n    return RoleRead.model_validate(role)\n","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/authz_roles.py#L217-L253","documentation":"Raised by PATCH /api/v1/authz/roles/{role_id} when session.commit() raises an IntegrityError. The route rolls back and maps any integrity failure to a 409 with this message; in practice it means the new name collides with another role's unique name constraint (a parent_role_id cycle or other constraint violation would surface here too, since the handler is not constraint-specific).","triggerScenarios":"PATCH /authz/roles/{id} renaming a role to a name already used by another role; creating a parent_role_id cycle that the DB rejects at commit.","commonSituations":"Case-sensitive vs case-insensitive unique indexes surprising callers (\"Admin\" vs \"admin\"); renaming during concurrent role administration where another request claimed the name between your GET and PATCH; seeding scripts that rename built-in roles to colliding names.","solutions":["Pick a different, unique name for the role","GET /api/v1/authz/roles first and check the desired name is not taken (note: still racy under concurrency)","Treat 409 as retryable with a new name — catch it in the client and prompt the user for a different name","If you were not renaming, inspect the server log for the underlying IntegrityError (parent_role_id cycle, etc.)"],"exampleFix":"// before\nawait updateRole(id, { name: 'admin' }); // another role already called 'admin'\n\n// after\nconst roles = await listRoles();\nconst name = roles.some(r => r.name === 'admin') ? 'admin-2' : 'admin';\nawait updateRole(id, { name });","handlingStrategy":"try-catch","validationCode":"async function isRoleNameFree(name: string) {\n  const roles = await (await fetch('/api/v1/authz/roles')).json();\n  return !roles.some(r => r.name === name);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await patchRole(id, body);\n} catch (e) {\n  if (e instanceof HttpException && e.status === 409) {\n    // prompt user for a new name; do not blind-retry the same name\n  } else throw e;\n}","preventionTips":["Check name availability before the PATCH, but still handle 409 (the check is racy)","Suggest auto-suffixed names (-2, -3) when a 409 hits a user-typed name"],"tags":["authz","api","roles","conflict","unique-constraint"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}