To list group-based licensing in Microsoft Entra ID, read the groups that have licences assigned, with each group's products and its licence processing state, then the members whose licence from the group failed. Licences reach a group's direct members only: a user in a group nested inside it gets nothing from the outer group.
| Method | Best fit |
|---|---|
| PowerShell | A tenant-wide CSV of licensed groups with their products, state, members and members in error. |
| Admin centre | Checking which groups 1 product is assigned to, and its assignment errors. |
| Altivane | Recommended for recurring licence reviews, with each group's users counted beside the assignment errors. |
Before you start
Use an account that can read groups and subscriptions, such as Global Reader. The PowerShell example requests Group.Read.All, and Organization.Read.All for the product names; your organisation may require administrator consent. The admin centre steps use the Licenses page of the Microsoft 365 admin centre.
Know what the state means. A group's processing state says whether Entra ID has finished applying its licences to the members. When a licence fails for 1 member, the failure is recorded on that person's account and shown later, not when the group was given the licence. The examples read and export; they do not assign, remove or reprocess any licence.
Option 1
List group-based licensing with PowerShell
Install the modules once, then connect and export every group that has a licence. The filter runs in Microsoft Graph, so groups without licences don't come back.
# Install once, if the modules are not already installed.
$modules = 'Microsoft.Graph.Authentication', 'Microsoft.Graph.Groups',
'Microsoft.Graph.Identity.DirectoryManagement', 'Microsoft.Graph.Users'
Install-Module $modules -Scope CurrentUser
$ErrorActionPreference = 'Stop'
Connect-MgGraph -Scopes 'Group.Read.All', 'Organization.Read.All' -NoWelcome
try {
$products = @{}
Get-MgSubscribedSku -All | ForEach-Object { $products[[string]$_.SkuId] = $_.SkuPartNumber }
$properties = 'id', 'displayName', 'assignedLicenses', 'licenseProcessingState'
$groups = @(Get-MgGroup -All -Filter 'assignedLicenses/any()' -Property $properties |
Sort-Object DisplayName)
$report = @(foreach ($group in $groups) {
$licences = foreach ($licence in $group.AssignedLicenses) {
$name = $products[[string]$licence.SkuId]
if (-not $name) { $name = [string]$licence.SkuId }
$off = ($licence.DisabledPlans | Measure-Object).Count
if ($off -gt 0) { $name += " ($off plans off)" }
$name
}
$members = @(Get-MgGroupMember -GroupId $group.Id -All)
$failed = @(Get-MgGroupMemberWithLicenseError -GroupId $group.Id -All)
[pscustomobject]@{
Group = $group.DisplayName
Licences = @($licences) -join '; '
ProcessingState = $group.LicenseProcessingState.State
DirectMembers = $members.Count
MembersWithErrors = $failed.Count
GroupId = $group.Id
}
})
if ($report.Count -eq 0) {
Write-Output 'No group in this tenant has a licence assigned.'
} else {
$report | Export-Csv -Path './group-based-licensing.csv' -NoTypeInformation -Encoding utf8
$inError = @($report | Where-Object { $_.MembersWithErrors -gt 0 }).Count
Write-Output "$($report.Count) groups assign licences; $inError have members in error."
}
} finally {
Disconnect-MgGraph | Out-Null
}
Each row is 1 group, with its products as codes such as SPE_E3 and how many of each product's service plans the group turns off. ProcessingState is ProcessingComplete once Entra ID has applied the licences. DirectMembers counts the group's own members, nested groups included, though those groups' members get nothing. MembersWithErrors is the row to act on.
List the errors in 1 group
Reconnect with Connect-MgGraph -Scopes 'Group.Read.All', 'User., then read why each member's licence from the group failed.
# Run while connected to Microsoft Graph. Replace the example group ID.
$groupId = '00000000-0000-0000-0000-000000000000'
Get-MgGroupMemberWithLicenseError -GroupId $groupId -All | ForEach-Object {
$user = Get-MgUser -UserId $_.Id -Property 'userPrincipalName', 'licenseAssignmentStates'
$user.LicenseAssignmentStates | Where-Object { $_.AssignedByGroup -eq $groupId } |
Select-Object @{ N = 'User'; E = { $user.UserPrincipalName } }, SkuId, State, Error
}
Option 2
Review group licences in the admin centre
- Sign in to the Microsoft 365 admin centre for the correct tenant.
- Go to Billing > Licenses.
- Select a product to open its details page, and find the groups it is assigned to in the list there.
- Select the Errors & issues tab for the users whose licence from a group failed, and select a user to see the error.
- Leave without assigning, unassigning or reprocessing anything.
This suits checking 1 product. Each product has a page of its own, so for every licensed group in the tenant at once, use PowerShell or a report.
Option 3 ยท Recommended for recurring licence reviews
Report on group-based licensing with Altivane
- Open Altivane and choose the tenant.
- Build the tenant's documents with the Licensing scorecard report in full, so the groups are listed as well as counted.
- Open the tenant's Excel workbook and find Group-Based Licensing: each group that assigns licences, with its products by name, its processing state (Queued, In progress, Complete or Failed) and how many users hold a licence through it.
- Read Licence Assignment Errors for each user whose licence failed, with the group in Assigned Via, and Licence Assignments for every licensed user and whether each product is direct or from a group.
A user whose assignment failed still counts towards the group. Where the groups can't be read, the table says it was not collected and Groups assigning licences says Not read, rather than 0. The scorecard rates assignment errors with Warning at 1 and Critical at 10 to start. Group-Based Licensing goes into both the Word report and the workbook.
Contact usCommon questions
Why does a member have no licence from the group?
Either the person is in a nested group, which group-based licensing doesn't support, or the assignment failed. The usual causes are not enough licences, a service plan that conflicts with one the person already has, and a usage location where the service isn't available. A member with no usage location gets the tenant's.
How do I clear an error once it's fixed?
Fix the cause, then select the group or user on Errors & issues and choose Reprocess; that step changes the tenant, so it is not part of this review. When the cause is a shortage, see how to find unused licences before buying more.
Can I move a user between licensed groups without a gap?
Yes. Add the person to the new group first, wait until the new licence shows on their account, then remove them from the old group. The other way round leaves them unlicensed until the new group is processed.
Microsoft references
Technical references checked on 7 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.