I ran into an interesting one today that had me scratching my head as to why we couldn’t move a user from Skype for Business On-Prem to Microsoft Teams.
Whenever we attempted to move a small bunch of users from on-prem to Teams the Skype for Business PowerShell Move-CsUser cmdlet would throw the error.
The user could not be moved because he or she has not been assigned a Team licence in Office 365. Users must be licenced before they can be moved to Teams
This error message was interesting, as my migration script uses my Teams Module that automatically licences users as well as checking and activating the relevant Service Plans in Microsoft 365.
Sure enough, I check the users and they are licenced for Teams and the Teams service plan (Apps tickbox) is enabled.
Even better the user shows up in Teams and is using it, So why can’t we move them?
So let’s see what’s really going on
First off we need to connect to Teams Online PowerShell and pull the user’s info with Get-CsOnlineUser
As the above can be quite overwhelming. It’s quite common for administrators to use Get-CsOnlineVoiceUser to pull up everything they need to know about the user, or maybe something like “Get-CsOnlineUser $username | Format-List DisplayName, EnterpriseVoiceEnabled, LineUri, TeamsUpgradeEffectiveMode” to filter down the massive amount of information that Teams PowerShell returns.
I’m going to tell you to add MCOValidationError to that list.
MCOValidationError is an XML property where Teams will store any error messages about enabling a user for Teams due to policy, licencing or AD Sync issues, if it’s blank it’s all good and you don’t need to worry about it. But it would be nice if the Teams Admin Center displayed this somewhere.
In this case, we have an AD data issue
in MCOValidationError, we get an error message suggesting the SIP Address is not unique
<ErrorRecord> <ErrorCode>NonUniqueSipAddress</ErrorCode> <ErrorDescription>The value of the msRTCSIP-PrimaryUserAddress or the SIP address in ProxyAddresses field in your local Active Directory is not unique. Correct the value in your local Active Directory. After you correct it, the value will be updated in your Microsoft Online Services directory during the next Active Directory synchronization.</ErrorDescription> </ErrorRecord>
Skype itself checks for unique sip addresses when provisioning users, so this is likely a mismatch between Teams and Skype.
First off, let’s check the user using Skype for Business PowerShell on-prem and confirm their SIP Address
Yep, that’s their address, now let’s ask Teams PowerShell who owns that SIP Address
In this case, the SIP address is being used by an old disabled account, which is preventing us from syncing up the new user account via AADSync.
If we check on-prem with the listed UPN, we can see it is indeed a disabled user, but no SIP Address is assigned.
However, when AADSync pushes the disabled user to AAD, Teams automatically provisions the user ready for when the account will be enabled (never)
I also checked in ADSIEdit too and sure enough, No msRTCPrimaryUserAddress (sip address) is defined
And unfortunately, the user has had their licence removed. So we cant just disable the Teams Service Plan on the account.
The fix in this case was simple,
- Grant the disabled user a licence that enables Teams
- Disable the Teams and Skype Online Service Plans (Untick it in the “Apps” list or remove the service plan via PowerShell)
- Wait for the Teams service to update its users to remove the offending disabled accounts (~15 min)
- Wait for AADSync to run and associate the freed up Sip address to the user
(Org dependant, check your O365 Admin centre for last sync time)
- Remove both the Teams and Skype Online Service plan from the “Good” user
- Wait for AADSync to run again
- Re-enable both the Teams and Skype Online Service plan from the “Good” user
- Check MCOValidationError has been cleared
- Try the migration again.
(If you get an error saying “Cant find user in active directory, disable the Teams service on the “Good” account, wait 5 minutes and enable it again)
Keep in mind, the MCOValidationError may be different for you, so it pays to have a read and see what’s going on!
There you have it, today we used the MCOValidationError property to find out what some user accounts were stuck on-prem.
If you found this helpful, please don’t forget to comment below. It helps other users find the same content.