NLog: PropertiesDictionary - Collection was modified exception

NLog version: 4.7.10
Platform: netstandard2.0

I have implemented custom NLog target inherited from NLog.Targets.TargetWithContext. The target calls GetAllProperties(LogEventInfo) method within Write(LogEventInfo):

protected override async void Write(LogEventInfo logEvent)
{
    // do something
    try
    {
        // do something
        IEnumerable<KeyValuePair<string, object>> properties = GetAllProperties(logEvent).ToList();
        foreach (KeyValuePair<string, object> property in properties)
        {
            // iterate properties
        }
        // await something
    }
    catch (Exception error)
    {
        InternalLogger.Error(error, "{0}[{1}]. Failed to send {2}.", GetType(), Name, logEvent);
    }
}

The target is used by an application with following configuration:

{
    "NLog": {
        "autoReload": true,
        "throwConfigExceptions": true,
        "internalLogLevel": "Debug",
        "internalLogFile": "${basedir}/Logs/nlog.log",
        "extensions": [{
                "assembly": "NLog.Extensions.Logging"
            }, {
                "assembly": "GrayNLog"
            }
        ],
        "default-wrapper": {
            "type": "AsyncWrapper",
            "overflowAction": "Block"
        },
        "targets": {
            "graylog": {
                "type": "UdpGelf",
                "host": "myhost.loc",
                "port": 12201,
                "layout": null,
                "contextProperties": [{
                        "name": "service",
                        "layout": "${appdomain:format={1\\}}"
                    }, {
                        "name": "serviceVersion",
                        "layout": "${assembly-version:type=Informational}"
                    }, {
                        "name": "log",
                        "layout": "${logger}"
                    }, {
                        "name": "error",
                        "layout": "${exception:format=toString}"
                    }
                ]
            }
        },
        "rules": [{
                "logger": "*",
                "writeTo": "graylog",
                "minLevel": "Trace"
            }
        ]
    }
}

The application uses following to apply the configuration:

hostBuilder.ConfigureLogging((context, logging) =>
{
    var configuration = context.Configuration.GetSection("NLog");
    NLog.LogManager.Configuration = new NLogLoggingConfiguration(configuration);
    logging
        .ClearProviders()
        .SetMinimumLevel(LogLevel.Trace)
        .AddNLog();
});

I was surprised to get following exception:

Exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute
at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
at NLog.Internal.PropertiesDictionary.DictionaryEnumeratorBase.MoveNextValidEventProperty()
at NLog.Targets.TargetWithContext.GetAllProperties(LogEventInfo logEvent, IDictionary`2 combinedProperties)

As you can see, I have tried to copy the dictionaty to list to avoid the exception. But it doesn’t help. Why is the dictionary modified after GetAllProperties returns it?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 18 (12 by maintainers)

Most upvoted comments

That’s great! The 4.7.12 version has treated my pain.