Skip to main content

Fix: ILogger Type Mismatch in AdapterWithErrorHandler CloudAdapter

· 2 min read
Jagdish Kumawat
Founder @ Dewiride

When creating an AdapterWithErrorHandler class that inherits from CloudAdapter, you might encounter this compile error:

Argument 3: cannot convert from 'Microsoft.Extensions.Logging.ILogger<Microsoft.Agents.Hosting.AspNetCore.IAgentHttpAdapter>' to 'Microsoft.Extensions.Logging.ILogger<Microsoft.Agents.Hosting.AspNetCore.CloudAdapter>'

This happens because you're passing ILogger<IAgentHttpAdapter> to the CloudAdapter base constructor, but it expects ILogger<CloudAdapter>.

The Problem Code

Here's the AdapterWithErrorHandler code that causes the compile error:

public class AdapterWithErrorHandler : CloudAdapter
{
public AdapterWithErrorHandler(IChannelServiceClientFactory channelServiceClientFactory, IActivityTaskQueue activityTaskQueue, ILogger<IAgentHttpAdapter> logger)
: base(channelServiceClientFactory, activityTaskQueue, logger: logger)
{
OnTurnError = async (turnContext, exception) =>
{
// Log any leaked exception from the application.
// NOTE: In production environment, you should consider logging this to
// Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
// to add telemetry capture to your bot.
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

// Only send error message for user messages, not for other message types so the bot doesn't spam a channel or chat.
if (turnContext.Activity.Type == ActivityTypes.Message)
{
// Send a message to the user
await turnContext.SendActivityAsync($"The bot encountered an unhandled error: {exception.Message}");
await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");

// Send a trace activity
await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
}
};
}
}

The issue is on line 3: ILogger<IAgentHttpAdapter> logger and passing it to the base constructor. The CloudAdapter expects ILogger<CloudAdapter>, not ILogger<IAgentHttpAdapter>.

Solution: Change Logger Type to CloudAdapter

Update your constructor to accept ILogger<CloudAdapter> instead:

public class AdapterWithErrorHandler : CloudAdapter
{
public AdapterWithErrorHandler(IChannelServiceClientFactory channelServiceClientFactory, IActivityTaskQueue activityTaskQueue, ILogger<CloudAdapter> logger)
: base(channelServiceClientFactory, activityTaskQueue, logger: logger)
{
OnTurnError = async (turnContext, exception) =>
{
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

if (turnContext.Activity.Type == ActivityTypes.Message)
{
await turnContext.SendActivityAsync($"The bot encountered an unhandled error: {exception.Message}");
await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
}
};
}
}

What changed:

  • Constructor parameter: ILogger<IAgentHttpAdapter>ILogger<CloudAdapter>
  • Now the logger type matches what CloudAdapter expects

Why This Happens

The CloudAdapter base class constructor signature expects:

CloudAdapter(..., ILogger<CloudAdapter> logger)

But your code was passing:

ILogger<IAgentHttpAdapter> logger

In .NET, ILogger<T> types are not interchangeable even if the classes are related. ILogger<CloudAdapter> and ILogger<IAgentHttpAdapter> are completely different types.

Summary

Change your constructor parameter to ILogger<CloudAdapter> and pass it to the base constructor. This aligns your adapter's logging category with the actual implementation class.

The .NET dependency injection container automatically provides ILogger<T> for any type T, so no additional registration is needed.

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.