Visitar URL original
System.ObjectDisposedException: Cannot access a disposed object · Issue #5755 · NLog/NLog · GitHub
Skip to content

System.ObjectDisposedException: Cannot access a disposed object #5755

Closed

Description

@daze99

I enabled throwConfigExceptions and I get the following error in the internal-log:

2025-03-28 08:46:28.7553 Warn Error has been raised. Exception: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at NLog.Config.ServiceRepositoryExtensions.GetService[T](IServiceProvider serviceProvider)

My Program.cs looks like this:

using NLog;
using NLog.Web;

using System.Diagnostics;

// NLog: setup the logger first to catch all errors
var logger = LogManager.Setup()
    .LoadConfigurationFromAppSettings()
    .GetCurrentClassLogger();

logger.Debug("init main");

try
{
    var builder = WebApplication.CreateBuilder(args);

    _ = builder.WebHost.ConfigureKestrel(options => options.AddServerHeader = false);

    // NLog: Setup NLog for Dependency injection
    _ = builder.Logging.ClearProviders();
    _ = builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
    _ = builder.Host.UseNLog(new NLogAspNetCoreOptions { RemoveLoggerFactoryFilter = false });

    var app = builder.ConfigureServices()
        .ConfigurePipeline();

    await app.RunAsync();
}
catch (Exception ex)
{
    // NLog: catch setup errors
    logger.Error(ex.Demystify(), "Stopped program because of exception");
    throw;
}
finally
{
    // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
    LogManager.Shutdown();
}

NLog version: 5.4.0

Platform: .NET8

Current NLog config

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      throwConfigExceptions="true"
      internalLogLevel="Warn"
      internalLogFile="${basedir}\nlog\internal-nlog.txt">

    <!-- enable ASP.NET Core layout renderers -->
    <extensions>
        <add assembly="NLog.Web.AspNetCore" />
        <add assembly="Microsoft.ApplicationInsights.NLogTarget" />
    </extensions>

    <!-- the targets to write to -->
    <targets async="true">
        <!-- File Target for all log messages with basic details -->
        <target xsi:type="File" name="allFile" fileName="${basedir}\nlog\nlog-all-${shortdate}.log"
                layout="${longdate} | ${event-properties:item=EventId:whenEmpty=0} | ${level:uppercase=true} | ${logger} | ${message} ${exception:format=tostring}"
                keepFileOpen="false" maxArchiveDays="21" />

        <!-- File Target for own log messages with extra web details using some ASP.NET core renderers -->
        <target xsi:type="File" name="ownFile" fileName="${basedir}\nlog\nlog-own-${shortdate}.log"
                layout="${longdate} | ${event-properties:item=EventId:whenEmpty=0} | ${level:uppercase=true} | ${logger} | ${message} ${exception:format=tostring} | url: ${aspnet-request-url} | action: ${aspnet-mvc-action} | ${callsite}"
                keepFileOpen="false" maxArchiveDays="21" />

        <!-- Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
        <target xsi:type="Console" name="lifetimeConsole" layout="${MicrosoftConsoleLayout}" />

        <!-- Application Insights Target -->
        <target xsi:type="ApplicationInsightsTarget" name="errorAi">
            <instrumentationKey>${configsetting:APPINSIGHTS.INSTRUMENTATIONKEY:whenEmpty=${environment:APPINSIGHTS_INSTRUMENTATIONKEY}}</instrumentationKey>
            <contextproperty name="threadid" layout="${threadid}" />
        </target>
    </targets>

    <!-- rules to map from logger name to target -->
    <rules>
        <!-- All logs, including from Microsoft -->
        <logger name="*" minlevel="Trace" writeTo="allFile" />

        <!-- Suppress output from Microsoft framework when non-critical -->
        <logger name="System.*" finalMinLevel="Warn" />
        <logger name="Microsoft.*" finalMinLevel="Warn" />

        <!-- Keep output from Microsoft.Hosting.Lifetime to console for fast startup detection -->
        <logger name="Microsoft.Hosting.Lifetime*" finalMinLevel="Info" writeTo="lifetimeConsole,ownFile" />

        <logger name="*" minlevel="Trace" writeTo="errorAi,ownFile">
            <filters defaultAction="Log">
                <when condition="contains('${exception:format=Type}', 'System.OperationCanceledException') or contains('${exception:format=Type}', 'System.Threading.Tasks.TaskCanceledException')" action="IgnoreFinal" />
                <when condition="'${logger}' == 'Duende.IdentityServer.Validation.TokenRequestValidator'" action="IgnoreFinal" />
                <when condition="'${logger}' == 'Microsoft.EntityFrameworkCore.Database.Connection' or '${logger}' == 'Microsoft.EntityFrameworkCore.Database.Command'" action="IgnoreFinal" />
                <when condition="contains('${exception:format=stacktrace}', 'System.Threading.Tasks.TaskCanceledException') or contains('${exception:format=stacktrace}', 'System.OperationCanceledException')" action="IgnoreFinal" />
                <when condition="'${logger}' == 'Microsoft.EntityFrameworkCore.Query' and contains('${exception}', 'Operation cancelled by user.')" action="IgnoreFinal" />
                <when condition="'${logger}' == 'Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer' and contains('${exception}', 'Operation cancelled by user.')" action="IgnoreFinal" />
                <when condition="'${logger}' == 'Duende.IdentityServer.Hosting.IdentityServerMiddleware' and contains('${exception}', 'Operation cancelled by user.')" action="IgnoreFinal" />
            </filters>
        </logger>
    </rules>
</nlog>

Activity

  1. snakefoot commented on Apr 2, 2025

    @snakefoot
    Contributor

    I'm not able to guess what triggers the GetService call, after the Microsoft Dependency Injection has been disposed.

    Possible that you can run your application using the Visual Studio Debugger, and get the full stacktrack of the exception, so we can see the full call chain?

  2. snakefoot commented on Apr 2, 2025

    @snakefoot
    Contributor

    Btw. it is recommend to use the LoggingRules instead of filters when possible:

        <!-- rules to map from logger name to target -->
        <rules>
            <!-- All logs, including from Microsoft -->
            <logger name="*" minlevel="Trace" writeTo="allFile" />
    
            <!-- Suppress output from Microsoft framework when non-critical -->
            <logger name="System.*" finalMinLevel="Warn" />
            <logger name="Microsoft.*" finalMinLevel="Warn" />
    
            <!-- Ignore noisy loggers -->
            <logger name="Duende.IdentityServer.Validation.TokenRequestValidator" finalMinLevel="Off" />
            <logger name="Microsoft.EntityFrameworkCore.Database.Connection" finalMinLevel="Off" />
            <logger name="Microsoft.EntityFrameworkCore.Database.Command" finalMinLevel="Off" />
    
            <!-- Keep output from Microsoft.Hosting.Lifetime to console for fast startup detection -->
            <logger name="Microsoft.Hosting.Lifetime*" finalMinLevel="Info" writeTo="lifetimeConsole,ownFile" />
    
            <logger name="*" minlevel="Trace" writeTo="errorAi,ownFile">
                <filters defaultAction="Log">
                    <when condition="contains('${exception:format=Type}', 'System.OperationCanceledException') or contains('${exception:format=Type}', 'System.Threading.Tasks.TaskCanceledException')" action="IgnoreFinal" />
                    <when condition="contains('${exception:format=stacktrace}', 'System.Threading.Tasks.TaskCanceledException') or contains('${exception:format=stacktrace}', 'System.OperationCanceledException')" action="IgnoreFinal" />
                    <when condition="'${logger}' == 'Microsoft.EntityFrameworkCore.Query' and contains('${exception}', 'Operation cancelled by user.')" action="IgnoreFinal" />
                    <when condition="'${logger}' == 'Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer' and contains('${exception}', 'Operation cancelled by user.')" action="IgnoreFinal" />
                    <when condition="'${logger}' == 'Duende.IdentityServer.Hosting.IdentityServerMiddleware' and contains('${exception}', 'Operation cancelled by user.')" action="IgnoreFinal" />
                </filters>
            </logger>
        </rules>
  3. daze99 commented on Apr 2, 2025

    @daze99
    Author

    Unfortunately I am not able to reproduce this issue on my local machine. It only happens in the app running on Azure.

    Another observation: The warning is not written immediately. It happens only after a while. Maybe this is related to the app being unloaded after inactivity.

    Also, I will change my filter to rules. Thanks for the hint.

  4. snakefoot commented on Apr 2, 2025

    @snakefoot
    Contributor
  5. snakefoot commented on May 28, 2025

    @snakefoot
    Contributor

    Resolved by #5756 with NLog v5.5

  6. added this to the 5.5 milestone on May 28, 2025
  7. snakefoot commented on May 29, 2025

    @snakefoot
    Contributor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions