PowerShell: Get-Team unreliable / returning incomplete results

%3CLINGO-SUB%20id%3D%22lingo-sub-2561467%22%20slang%3D%22en-US%22%3EPowerShell%3A%20Get-Team%20unreliable%20%2F%20returning%20incomplete%20results%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2561467%22%20slang%3D%22en-US%22%3E%3CP%3EHi%2C%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EWe%20have%20multiple%20issues%20with%20the%20Get-Team%20cmdlet%20in%20the%20MicrosoftTeams%20module%20(v2.3.0).%20Like%20many%20organisations%2C%20we're%20programmatically%20creating%20Teams%20based%20on%20organisational%20data%20(e.g.%20one%20Team%20to%20support%20one%20Dept%2FModule%2Fsome%20other%20business%20unit).%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EHowever%2C%20Get-Team%20often%20fails%20to%20return%20Teams%20that%20we%20have%20previously%20created%20(and%20do%20still%20exist%20in%20Microsoft-land).%20This%20makes%20the%20data%20untrustworthy%20and%20very%20difficult%20to%20deal%20with.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThis%20problem%20can%20surface%20in%20multiple%20ways%3A%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%3CSTRONG%3E1)%20Running%20%22Get-Team%22%20to%20retrieve%20all%20teams%3C%2FSTRONG%3E%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CUL%3E%3CLI%3EResults%20are%20often%20incomplete.%20When%20this%20happens%2C%20there%20are%20usually%20around%201-5%20'missing'%20from%20what%20we%20expect%2C%20out%20of%20around%204000%20Teams.%26nbsp%3B%3C%2FLI%3E%3C%2FUL%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%3CSTRONG%3E2)%20Running%20%22Get-Team%20-MailNickName%22%20to%20query%20for%20a%20specific%20Team.%26nbsp%3B%3C%2FSTRONG%3E%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CUL%3E%3CLI%3EThis%20will%20sometimes%20fail%20to%20find%20a%20Team.%20We%20can%20run%20a%20loop%20100%20times%20(with%203%20second%20wait)%20and%20it%20fails%20to%20find%20the%20Team%20100%20times.%20The%20next%20day%2C%20the%20Team%20is%20found%20100%20times.%20Sometimes%20for%20example%2C%20it's%20found%20only%2095%20times%20out%20of%20100.%26nbsp%3B%3C%2FLI%3E%3CLI%3EUnder%20the%20hood%2C%20it's%20using%20the%20Graph%20API.%20Example%20of%20a%20Team%20that%20exists%2C%20has%20an%20associated%20UnifiedGroup%20with%20ResourceProvisioningOptions%3DTeam)%3A%3C%2FLI%3E%3C%2FUL%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3EGet-Team%20-MailNickName%20'thisisateam'%20-Verbose%20-Debug%0A%0AVERBOSE%3A%20Done%20performing%20authorization%0AVERBOSE%3A%20Executing%20Get-Team%20for%20parameters%20GroupId%3A%20%2C%20User%3A%20%2C%20Archived%3A%20%2C%20Visibility%3A%20%2C%20DisplayName%3A%20%2C%20MailNickName%3A%20thisisateam%0ADEBUG%3A%20Making%20an%20api%20call%20to%20the%20uri%3A%20https%3A%2F%2Fgraph.microsoft.com%2Fbeta%2Fgroups%3F%24filter%3DresourceProvisioningOptions%2FAny(x%3Ax%20eq%20'Team')%26amp%3B%24top%3D20%26amp%3B%24count%3Dtrue%26amp%3B%24search%3D%22mailNickname%3Athisisateam%22%0ADEBUG%3A%20Returning%200%20teams%0AVERBOSE%3A%20Retrieving%20groups%20list%0AVERBOSE%3A%20Done%20retrieving%20groups%2C%20getting%20team%20properties%0AVERBOSE%3A%20Done%20processing%20Get-Team%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EHas%20anyone%20else%20experienced%20this%3F%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThe%20other%20issue%20is%20that%20-MailNickName%20doesn't%20return%20unique%20results%20and%20instead%20defaults%20to%20some%20kind%20of%20wildcard%20match%20rather%20than%20making%20a%20wildcard%20search%20optional.%20This%20is%20a%20problem%20for%20efficiently%20querying%20for%20data%20but%20can%20be%20worked%20around%20(by%20inefficiently%20passing%20all%20results%20to%20Where-Object)%2C%20but%20I%20don't%20want%20to%20detract%20too%20much%20from%20the%20more%20urgent%20problem%20of%20unreliable%20data%20being%20returned.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EHelp%20much%20appreciated.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThank%20you.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-2561467%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EDeveloper%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EMicrosoft%20Teams%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-2561685%22%20slang%3D%22en-US%22%3ERe%3A%20PowerShell%3A%20Get-Team%20unreliable%20%2F%20returning%20incomplete%20results%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2561685%22%20slang%3D%22en-US%22%3E%3CP%3EHere%20is%20an%20example%20script%20which%20proves%20the%20problem%20when%20obtaining%20all%20Teams.%20I've%20had%20results%20between%204454%20and%204457%2C%20in%20a%20tenancy%20where%20no%20Teams%20are%20being%20created%20or%20deleted%20currently.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%24LoopCount%20%3D%201%0A%24Loops%20%3D%2010%0A%24WaitTimeSeconds%20%3D%20400%0Ado%0A%7B%0A%20%20%20%20if(%24AllTeams)%20%7B%20%24PreviousLoopData%20%3D%20%24AllTeams%20%7D%0A%0A%20%20%20%20Write-Output%20%22Get-Team%20Attempt%20%24LoopCount%20%7C%20%24(Get-Date%20-Format%20'yyyy-MM-dd-HH-mm-ss')%22%0A%20%20%20%20try%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24AllTeams%20%3D%20Get-Team%20-ErrorAction%20Stop%0A%20%20%20%20%20%20%20%20Write-Output%20%22Total%20Teams%20Found%3A%20%24(%24AllTeams.Count)%22%0A%0A%20%20%20%20%20%20%20%20if(%24PreviousLoopData)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24Diffs%20%3D%20Compare-Object%20-ReferenceObject%20%24PreviousLoopData%20-DifferenceObject%20%24AllTeams%20-Property%20MailNickName%0A%20%20%20%20%20%20%20%20%20%20%20%20%24NewButNotReally%20%3D%20%24Diffs%20%7C%20Where-Object%20%7B%20%24_.SideIndicator%20-eq%20'%3D%26gt%3B'%20%7D%20%7C%20Select-Object%20-Expand%20MailNickName%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24NewButNotReally)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Write-Output%20%22%20%20%20%20-%20Comparison%20between%20previous%20loop%20and%20this%20loop%20suggests%20the%20following%20Teams%20have%20been%20CREATED%3A%20%24(%24NewButNotReally%20-join%20'%2C%20')%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%24DeletedButNotReally%20%3D%20%24Diffs%20%7C%20Where-Object%20%7B%20%24_.SideIndicator%20-eq%20'%26lt%3B%3D'%20%7D%20%7C%20Select-Object%20-Expand%20MailNickName%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24DeletedButNotReally)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Write-Output%20%22%20%20%20%20-%20Comparison%20between%20previous%20loop%20and%20this%20loop%20suggests%20the%20following%20Teams%20have%20been%20DELETED%3A%20%24(%24DeletedButNotReally%20-join%20'%2C%20')%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20catch%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24_%0A%20%20%20%20%7D%0A%20%20%20%20Start-Sleep%20-Seconds%20%24WaitTimeSeconds%0A%20%20%20%20%24LoopCount%2B%2B%0A%7D%20until%20(%24LoopCount%20-ge%2011)%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CDIV%3E%3CDIV%3E%3CDIV%3E%3CDIV%3EYou'll%20see%20things%20like%3A%20%22Comparison%26nbsp%3Bbetween%26nbsp%3Bprevious%26nbsp%3Bloop%26nbsp%3Band%26nbsp%3Bthis%26nbsp%3Bloop%26nbsp%3Bsuggests%26nbsp%3Bthe%26nbsp%3Bfollowing%26nbsp%3BTeams%26nbsp%3Bhave%26nbsp%3Bbeen%26nbsp%3BDELETED%3A%20XXX%2C%20YYY%22%3CBR%20%2F%3E...%20and%20then%20in%20the%20following%20loop%20when%20they%20reappear%20again%3A%26nbsp%3B%22Comparison%26nbsp%3Bbetween%26nbsp%3Bprevious%26nbsp%3Bloop%26nbsp%3Band%26nbsp%3Bthis%26nbsp%3Bloop%26nbsp%3Bsuggests%26nbsp%3Bthe%26nbsp%3Bfollowing%26nbsp%3BTeams%26nbsp%3Bhave%26nbsp%3Bbeen%20CREATED%3A%20XXX%2C%20YYY%22%3C%2FDIV%3E%3C%2FDIV%3E%3C%2FDIV%3E%3C%2FDIV%3E%3C%2FLINGO-BODY%3E
New Contributor

Hi,

 

We have multiple issues with the Get-Team cmdlet in the MicrosoftTeams module (v2.3.0). Like many organisations, we're programmatically creating Teams based on organisational data (e.g. one Team to support one Dept/Module/some other business unit).

 

However, Get-Team often fails to return Teams that we have previously created (and do still exist in Microsoft-land). This makes the data untrustworthy and very difficult to deal with.

 

This problem can surface in multiple ways:

 

1) Running "Get-Team" to retrieve all teams

 

  • Results are often incomplete. When this happens, there are usually around 1-5 'missing' from what we expect, out of around 4000 Teams. 

 

2) Running "Get-Team -MailNickName" to query for a specific Team. 

 

  • This will sometimes fail to find a Team. We can run a loop 100 times (with 3 second wait) and it fails to find the Team 100 times. The next day, the Team is found 100 times. Sometimes for example, it's found only 95 times out of 100. 
  • Under the hood, it's using the Graph API. Example of a Team that exists, has an associated UnifiedGroup with ResourceProvisioningOptions=Team):

 

Get-Team -MailNickName 'thisisateam' -Verbose -Debug

VERBOSE: Done performing authorization
VERBOSE: Executing Get-Team for parameters GroupId: , User: , Archived: , Visibility: , DisplayName: , MailNickName: thisisateam
DEBUG: Making an api call to the uri: https://graph.microsoft.com/beta/groups?$filter=resourceProvisioningOptions/Any(x:x eq 'Team')&$top=20&$count=true&$search="mailNickname:thisisateam"
DEBUG: Returning 0 teams
VERBOSE: Retrieving groups list
VERBOSE: Done retrieving groups, getting team properties
VERBOSE: Done processing Get-Team

 

 

Has anyone else experienced this? 

 

The other issue is that -MailNickName doesn't return unique results and instead defaults to some kind of wildcard match rather than making a wildcard search optional. This is a problem for efficiently querying for data but can be worked around (by inefficiently passing all results to Where-Object), but I don't want to detract too much from the more urgent problem of unreliable data being returned.

 

Help much appreciated.

 

Thank you.

 

 

3 Replies

Here is an example script which proves the problem when obtaining all Teams. I've had results between 4454 and 4457, in a tenancy where no Teams are being created or deleted currently.

 

$LoopCount = 1
$Loops = 10
$WaitTimeSeconds = 400
do
{
    if($AllTeams) { $PreviousLoopData = $AllTeams }

    Write-Output "Get-Team Attempt $LoopCount | $(Get-Date -Format 'yyyy-MM-dd-HH-mm-ss')"
    try
    {
        $AllTeams = Get-Team -ErrorAction Stop
        Write-Output "Total Teams Found: $($AllTeams.Count)"

        if($PreviousLoopData)
        {
            $Diffs = Compare-Object -ReferenceObject $PreviousLoopData -DifferenceObject $AllTeams -Property MailNickName
            $NewButNotReally = $Diffs | Where-Object { $_.SideIndicator -eq '=>' } | Select-Object -Expand MailNickName
            if($NewButNotReally)
            {
                Write-Output "    - Comparison between previous loop and this loop suggests the following Teams have been CREATED: $($NewButNotReally -join ', ')"
            }
            $DeletedButNotReally = $Diffs | Where-Object { $_.SideIndicator -eq '<=' } | Select-Object -Expand MailNickName
            if($DeletedButNotReally)
            {
                Write-Output "    - Comparison between previous loop and this loop suggests the following Teams have been DELETED: $($DeletedButNotReally -join ', ')"
            }
        }
    }
    catch
    {
        $_
    }
    Start-Sleep -Seconds $WaitTimeSeconds
    $LoopCount++
} until ($LoopCount -ge 11)

 

You'll see things like: "Comparison between previous loop and this loop suggests the following Teams have been DELETED: XXX, YYY"
... and then in the following loop when they reappear again: "Comparison between previous loop and this loop suggests the following Teams have been CREATED: XXX, YYY"
I've just faced a similar issue with the same cmdlet.

1. Here the output seems to be correct
PS H:\> $teams = get-team -user <my UPN here> -Archived $False
PS H:\> $teams.count
18

2. WTF???
PS H:\> $teams = Get-Team -Archived $false
PS H:\> $teams.count
4


Regarding the -MailNickName filtering, they have a note at https://docs.microsoft.com/en-us/powershell/module/teams/get-team?view=teams-ps, saying this:

"Get-Team may return multiple results matching the input and not just the exact match for attributes like DisplayName/MailNickName. This is known behavior."

If "known behavior" is a new name for a bug then we may hope it gets fixed eventually.