Microsoft Graph Error: Microsoft.Kiota.Http.HttpClientLibrary: Failed to execute GetChildThreadsV2Async

Tran, Nguyen 20 Reputation points
2024-05-16T16:57:31.6266667+00:00

Context: I'm trying to create an Azure Function that pulls Teams and Channels info using Graph API. As I understand it (please correct me if I'm wrong), there's no way to send one Graph API request to retrieve all channels in my organization, and I have to first fetch all Teams and then for each Team, fetch the channels.

As there are more than 28,000 Teams, the time it takes to fetch all channels by iterating through each Team at a time is slow, so I try to fetch channels from multiple Teams concurrently, as shown by this code block in my Function:

// ...
// ...
// ...
// the code above this fetches all Teams in my org

log.LogInformation($"Getting all channels.");

// create a semaphore to limit the number of concurrent requests
var maxConcurrentRequests = 15; // adjust this value as needed
var semaphore = new SemaphoreSlim(maxConcurrentRequests);

// counter for the number of teams done
int teamsDone = 0;

// fetch the channels for all teams concurrently, but limit the number of concurrent requests
var tasks = teamsList.Select(async team =>
{
await semaphore.WaitAsync();

try
{
    log.LogInformation($"Fetching channels for team: {team.Id} - {team.DisplayName}");
    var channels = await graphClient.Teams[team.Id].Channels.GetAsync();

    foreach (var channel in channels.Value)
    {
        TeamsChannels.Add((team.Id, team.DisplayName, team.Mail,
                            channel.Id, channel.DisplayName, channel.Email,
                            channel.Description));
        ++channelCount;
    }

    // log.LogInformation($"Team: {team.DisplayName} has {channels.Value.Count} channels.");

    // increment the counter and log the progress
    var done = Interlocked.Increment(ref teamsDone);
    log.LogInformation($"FETCHING CHANNELS PROGRESS: {done}/{teamsList.Count}");
}
finally
{
    // Release is called to release the semaphore, allowing another request to be made
    semaphore.Release();
}
});
await Task.WhenAll(tasks);

However, as it was almost done fetching all channels (got to 28565/28625) then I received this error:

System.Private.CoreLib: Exception while executing function: GetTeamsChannels. Microsoft.Kiota.Http.HttpClientLibrary: Failed to execute GetChildThreadsV2Async.

Could someone please help me resolve this error?

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
4,421 questions
Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,913 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,419 questions
0 comments No comments
{count} votes

Accepted answer
  1. hossein jalilian 4,385 Reputation points
    2024-05-16T17:55:03.7466667+00:00

    Thanks for posting your question in the Microsoft Q&A forum.

    As far as I know, you can use batch requests to retrieve data and reduce your request rate. The error you're encountering might be due to rate limitations.

    using Microsoft.Graph;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Threading.Tasks;
    public static async Task<IList<Team>> GetTeamsWithChannels(GraphServiceClient graphClient)
    {
        var teams = new List<Team>();
        
        var teamsRequest = await graphClient.Teams.Request().GetAsync();
        teams.AddRange(teamsRequest.CurrentPage);
        var batchRequestsList = new List<BatchRequestContent>();
        foreach (var team in teams)
        {
            var channelsRequest = graphClient.Teams[team.Id].Channels.Request();
            batchRequestsList.Add(new BatchRequestContent(channelsRequest));
        }
        var batchRequestsBody = new BatchRequestContent(batchRequestsList);
        await graphClient.BatchRequest.Request().PostAsync(batchRequestsBody);
        foreach (var batchResponse in batchRequestsBody.Responses)
        {
            if (batchResponse.Status == 200)
            {
                //...
            }
        }
        return teams;
    }
    
    

    Please don't forget to close up the thread here by upvoting and accept it as an answer if it is helpful

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful