Skip to content
🎉 Launch sale:50% off everything over $22 — automatically applied at checkout· ends Aug 2Shop the sale →
DevOps AI ToolKit
Newsletter
All guides
Azure with AI By James Joyner IV · · 7 min read Last reviewed Jul 2026

Azure Error: 'RoleAssignmentExists: The role assignment already exists' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix Azure RoleAssignmentExists: the role assignment already exists. Make grants idempotent with a deterministic GUID or detect the existing assignment first.

  • #azure
  • #cloud
  • #troubleshooting
  • #errors
  • #rbac
Free toolkit

Stuck on this Azure with AI error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

What this error means

Azure returns RoleAssignmentExists when you try to create a role assignment (principal + role definition + scope) that already exists. Azure treats the triple as unique, so a second create — common in re-run pipelines and non-idempotent IaC — is rejected rather than silently ignored. The literal error:

{
  "error": {
    "code": "RoleAssignmentExists",
    "message": "The role assignment already exists."
  }
}

It is a benign error in the sense that the desired state (the grant) is already true, but it fails a deployment or script that does not treat it as idempotent.

What users report

  • az role assignment create exits non-zero with RoleAssignmentExists on a re-run.
  • A Bicep/ARM Microsoft.Authorization/roleAssignments deployment fails on the second apply.
  • A pipeline that grants a managed identity access works the first time and fails every time after.
  • The error appears even though functionally nothing needs to change.

Tenant and app configuration causes

  • Non-idempotent re-run — the same grant is attempted again on a repeat pipeline execution or a terraform apply/az deployment re-run.
  • Random GUID for the assignment name — ARM role assignments are named by GUID; using guid(newGuid()) or a random value creates a new assignment name for the same triple, which ARM then rejects as a duplicate of the existing one.
  • Parallel grants — two concurrent steps grant the same role to the same principal at the same scope.
  • Inherited assignment — the principal already has the role at a higher scope, and a redundant identical assignment is attempted at the same scope.

Confirming tenant configuration

Check whether the assignment already exists for that principal, role, and scope:

az role assignment list \
  --assignee <objectId-or-appId> \
  --role "Storage Blob Data Contributor" \
  --scope "/subscriptions/1111.../resourceGroups/data-rg" \
  -o table

If a row comes back, the grant is already in place and the create is redundant. Inspect its name (the GUID) and whether it is inherited from a parent scope:

az role assignment list \
  --assignee <objectId> --all \
  --query "[].{Role:roleDefinitionName, Scope:scope, Name:name}" -o table

An entry whose scope is broader than your target scope means the principal already holds the role by inheritance.

Resolution

Make CLI grants idempotent — check first, create only if missing:

if ! az role assignment list --assignee <objectId> \
     --role "Reader" --scope <scope> --query "[0]" -o tsv | grep -q .; then
  az role assignment create --assignee <objectId> --role "Reader" --scope <scope>
fi

Use a deterministic GUID in ARM/Bicep so re-deploys map to the same assignment and become a no-op instead of a duplicate:

resource ra 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(subscription().id, principalId, roleDefinitionId)
  properties: {
    principalId: principalId
    roleDefinitionId: roleDefinitionId
    principalType: 'ServicePrincipal'
  }
}

The guid(scope, principalId, roleDefinitionId) pattern yields a stable name for a stable triple, so ARM recognizes it as already-present and returns success.

In Terraform, if the assignment was created outside state, import it rather than re-creating:

terraform import azurerm_role_assignment.this <role-assignment-id>

If it is already inherited from a parent scope, simply remove the redundant grant from your template — the access is already effective.

Avoiding tenant drift

  • Random names are the usual trap. newGuid() (non-deterministic) regenerates on every deploy and guarantees this error; always derive the name from the triple.
  • Deleting to “fix” it can break access. Do not delete the existing assignment to allow a fresh create unless you are sure nothing depends on it in the meantime.
  • principalType matters for new identities. When granting to a just-created managed identity, set principalType: 'ServicePrincipal' so ARM does not fail replication checks and then leave a partial state that looks like a duplicate.
  • Inheritance is invisible to a scoped list. Add --all to az role assignment list to see grants inherited from management group or subscription scope.
Free download · 368-page PDF

Fixed it? Get 500 Azure with AI & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.