Fix: ILogger Type Mismatch in AdapterWithErrorHandler CloudAdapter
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
CloudAdapterexpects
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.
