Forum Discussion

Cauldron_of_Penguins's avatar
Cauldron_of_Penguins
Copper Contributor
Sep 05, 2019

Handling CSOM 429 Errors from PowerShell Scripts

I have a PowerShell script which processes a large number of lists, it *will* get 429 errors.

I could put a sleep in there, but how long? Too long will make an already long-running script unnecessarily slow, so I want to handle the 429's and respect the Retry-After.

 

I've got a test script like this, which I run many times concurrently for force threshold errors: 

 

for($i=0; $i -lt 10000; $i++) 
{
    Write-Verbose "Attempt $($i)" -Verbose
    $caml = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
    $items = $lib.GetItems($caml)
    try
    {
        $ctx.Load($items)
        $ctx.ExecuteQuery()
        Write-Verbose "Found $($items.Count) items" -Verbose
    }
    catch
    {
        Write-Warning $_
        Start-Sleep -Seconds 20
    }
}

 

 

When I watch the scripts running in Fiddler I *do* see the Retry-After header. 

 

Question: How do I get the Response Headers from my ExecuteQuery?

5 Replies

  • Anonymous's avatar
    Anonymous

    Cauldron_of_Penguins 

     

    I had this same 429 issue.

     

    Doing "decorate" thing did not make a difference, and adding a few seconds of "sleep" between each update helped a little bit but did not fully resolve the problem.

     

    I resolved it by using ExecuteQueryAsync() instead of ExecuteQuery().

  • Kevin_Morgan's avatar
    Kevin_Morgan
    Iron Contributor

    Cauldron_of_Penguins 

     

    Hope you have to get Retry-After field from catched error object.

    try
    {
       .......................
    }
    catch
    {   
        Write-Host "Retry-After:" $_.Exception.Response.Headers["Retry-After"] 
    }

     

    • Cauldron_of_Penguins's avatar
      Cauldron_of_Penguins
      Copper Contributor

      Kevin_Morgan 

      Hey Kevin, I put a breakpoint in my catch block. 

      $_ looks good (it's the correct exception), but $_.Response is null.

       

       

      Hit Line breakpoint on 'C:\Users\..\Desktop\Testing\LVT Test.ps1:44'
      07:35:59 .\Desktop > $_.Exception.Response.Headers["Retry-After"]
      Cannot index into a null array.
      At line:1 char:1
      + $_.Exception.Response.Headers["Retry-After"]
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
          + FullyQualifiedErrorId : NullArray
       
      
      07:36:05 .\Desktop > $_
      Exception calling "ExecuteQuery" with "0" argument(s): "The remote server returned an 
      error: (429)."
      At C:\Users\..\Desktop\Testing\LVT 
      Test.ps1:39 char:9
      +         $ctx.ExecuteQuery()
      +         ~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
          + FullyQualifiedErrorId : WebException
       
      
      07:36:13 .\Desktop > $_.ResPonse
      
      07:36:22 .\Desktop > $_.ResPonse -eq $null
      True
      
      07:36:44 .\Desktop > 

       

       

       

      I tried to get the Response details with: 

       

      $streamReader = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream())
      $ErrResp = $streamReader.ReadToEnd()
      $streamReader.Close()
      Write-Verbose $ErrResp 

       

      This get me the string '429 TOO MANY REQUESTS' which might be workable to identify it as a 429 (I wonder if it will always be in English..?). I don't see the response Retry-After.

       

Resources