medusajs/medusa · error · Error
Cannot create role parent relationship: a role cannot be its
Error message
Cannot create role parent relationship: a role cannot be its own parent (role_id: ${role_id}) What it means
Thrown by the RBAC module when creating role-parent relationships if a role is specified as its own parent (role_id === parent_id). This guard runs before persistence in createRbacRoleParents, preventing self-referential hierarchy rows that would break permission inheritance traversal.
Source
Thrown at packages/modules/rbac/src/services/rbac-module-service.ts:250
for (const role of roles) {
role.policies = policiesByRole.get(role.id) || []
}
}
return [roles as unknown as RbacRoleDTO[], count]
}
@InjectManager()
// @ts-expect-error
async createRbacRoleParents(
data: CreateRbacRoleParentDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<RbacRoleParentDTO[]> {
for (const parent of data) {
const { role_id, parent_id } = parent
if (role_id === parent_id) {
throw new Error(
`Cannot create role parent relationship: a role cannot be its own parent (role_id: ${role_id})`
)
}
const wouldCreateCycle = await this.rbacRepository_.checkForCycle(
role_id,
parent_id,
sharedContext
)
if (wouldCreateCycle) {
throw new Error(
`Cannot create role parent relationship: this would create a circular dependency (role_id: ${role_id}, parent_id: ${parent_id})`
)
}
}
return await super.createRbacRoleParents(data, sharedContext)View on GitHub (pinned to 5e06e544a2)
Solutions
- Fix the caller to omit or choose a different parent_id when it equals role_id
- If a role should have no parent, delete the existing parent relation instead of creating a self-relation
- Add client-side validation to disable selecting the role itself in parent pickers
Example fix
// before
await rbacService.createRbacRoleParents([
{ role_id: roleId, parent_id: roleId },
])
// after
await rbacService.createRbacRoleParents([
{ role_id: roleId, parent_id: differentRoleId },
]) Defensive patterns
Strategy: validation
Validate before calling
function assertNotSelfParent(rels: { role_id: string; parent_id: string }[]) {
const bad = rels.filter((r) => r.role_id === r.parent_id)
if (bad.length) throw new Error(`Self-parent for roles: ${bad.map((b) => b.role_id).join(", ")}`)
} Type guard
function isValidParentRelation(rel: { role_id: string; parent_id: string }): boolean {
return rel.role_id !== rel.parent_id
} Try / catch
try {
await rbacService.createRbacRoleParents(payload)
} catch (e) {
if (/cannot be its own parent/.test(e.message)) {
payload = payload.filter((r) => r.role_id !== r.parent_id)
} else throw e
} Prevention
- Filter self-relations out of bulk payloads before submit
- Disable the current role in parent-selection UIs
- Validate in a workflow step before the service call
When it happens
Trigger: Calling createRbacRoleParents (directly or via workflows like setRoleParentStep / createRbacRoleParents workflow) with a payload where role_id equals parent_id, e.g. { role_id: 'role_1', parent_id: 'role_1' }.
Common situations: UI bugs that preselect the current role as its own parent, scripts copying role hierarchies that accidentally include the root role as its own parent, or defaulting parent_id to role_id when no parent is chosen.
Related errors
- Cannot create role parent relationship: this would create a
- Cannot update role parent relationship: a role cannot be its
- Role with id: ${req.params.id} not found
- Cannot update role parent relationship: this would create a
- --paths must be a directory - ${additionalPath}
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/f395a70e0690d8f8.
Report an issue: GitHub.