{"record":{"id":"c72cf943390b9868","repo":"langflow-ai/langflow","slug":"parent-role-id-does-not-reference-an-existing-role","errorCode":null,"errorMessage":"parent_role_id does not reference an existing role","messagePattern":"parent_role_id does not reference an existing role","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"src/backend/base/langflow/api/v1/authz_roles.py","lineNumber":118,"sourceCode":"    if role is None:\n        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=\"Role not found\")\n    return RoleRead.model_validate(role)\n\n\n@router.post(\"\", response_model=RoleRead, status_code=status.HTTP_201_CREATED)\n@router.post(\"/\", response_model=RoleRead, status_code=status.HTTP_201_CREATED)\nasync def create_role(\n    payload: RoleCreate,\n    current_user: CurrentActiveUser,\n    session: DbSession,\n) -> RoleRead:\n    \"\"\"Create a custom (non-system) role. Superuser-only.\"\"\"\n    _require_superuser(current_user)\n\n    if payload.parent_role_id is not None:\n        parent = await session.get(AuthzRole, payload.parent_role_id)\n        if parent is None:\n            raise HTTPException(\n                status_code=status.HTTP_400_BAD_REQUEST,\n                detail=\"parent_role_id does not reference an existing role\",\n            )\n\n    role = AuthzRole(\n        name=payload.name,\n        description=payload.description,\n        is_system=False,\n        permissions=list(payload.permissions),\n        parent_role_id=payload.parent_role_id,\n        created_by=current_user.id,\n    )\n    session.add(role)\n    try:\n        await session.commit()\n    except IntegrityError as exc:\n        await session.rollback()\n        raise HTTPException(","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/authz_roles.py#L100-L136","documentation":"Raised by POST /api/v1/authz/roles when the optional parent_role_id in RoleCreate does not reference an existing AuthzRole. The route validates the parent with session.get before inserting, returning HTTP 400 rather than surfacing a DB foreign-key error.","triggerScenarios":"POST {\"name\": \"new-role\", \"parent_role_id\": \"<unknown-uuid>\"} — parent was deleted, belongs to another install, or the UUID is malformed-but-parseable.","commonSituations":"Building role hierarchies from exported config where parent roles were not imported first, or referencing a parent deleted by another admin between form load and submit.","solutions":["Create/import parent roles before children","Resolve parent ids by name from GET /api/v1/authz/roles at request time","On 400, re-fetch the roles list and let the user repick the parent"],"exampleFix":"// before\napi.post('/authz/roles', { name: 'junior-dev', parent_role_id: savedId });\n\n// after\nconst roles = await api.get('/authz/roles');\nconst parent = roles.find(r => r.name === 'developer');\nif (!parent) throw new Error('parent role missing');\nawait api.post('/authz/roles', { name: 'junior-dev', parent_role_id: parent.id });","handlingStrategy":"validation","validationCode":"const roles = await api.get('/api/v1/authz/roles');\nif (payload.parent_role_id && !roles.some(r => r.id === payload.parent_role_id)) {\n  throw new Error('parent role does not exist');\n}","typeGuard":null,"tryCatchPattern":"catch (e) { if (e.status === 400) { await reloadRoles(); repickParent(); } }","preventionTips":["Create parents before children when importing hierarchies","Resolve parent ids by name at request time","Re-validate the parent exists on submit if the form has been open a while"],"tags":["authz","rbac","http-400","roles","validation"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}