Skip to content

Change in 3.4.0: missing event source error is now returned from "XmlConfigurator.ConfigureAndWatch" #332

Closed

Description

@WolfgangHG

There must have been a change in 3.4.0 that makes my code fail on my development machine: my Log4Net config defines an EventLogAppender, and this fails if the event log registry key is not set:

[EventLogAppender] ErrorCode: GenericFailure. Caught a SecurityException trying to access the EventLog. Most likely the event source Sample Application doesn't exist and must be created by a local administrator. Will disable EventLogAppender. See http://logging.apache.org/log4net/release/faq.html#trouble-EventLog

My Log4Net config looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="EventLogAppender" type="Log4Net.Appenders.NetCore.EventLogAppender,Log4Net.Appenders.NetCore">
    <param name="LogName" value="Sample Log" />
    <param name="ApplicationName" value="Sample Application" />

    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="ERROR" />
      <levelMax value="FATAL" />
    </filter>
  </appender>

  <root>
    <level value="INFO" />
    <appender-ref ref="EventLogAppender" />
  </root>

</log4net>

When activating Log4Net, I use XmlConfigurator.ConfigureAndWatch and fail if the resulting error collection contains anything - in this case logging is misconfigured and don't want to continue.

With 3.4.0, the error messages contain an error (see above) if there is no key Computer\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\EventLog\Sample Log\Sample Application. So my Log4Net initialization fails.

With 3.3.2, there is no error message, the errors are caught internally.

The error happens internally, the stack trace is the same for both versions:

System.Security.SecurityException
  HResult=0x8013150A
  Message=Requested registry access is not allowed.
  Source=Microsoft.Win32.Registry
  StackTrace:
   at
 	Microsoft.Win32.Registry.dll!Microsoft.Win32.RegistryKey.OpenSubKey(string name, bool writable)	Unknown
 	System.Diagnostics.EventLog.dll!System.Diagnostics.EventLog.GetEventLogRegKey(string machine, bool writable)	Unknown
 	System.Diagnostics.EventLog.dll!System.Diagnostics.EventLog.FindSourceRegistration(string source, string machineName, bool readOnly, bool wantToCreate)	Unknown
 	System.Diagnostics.EventLog.dll!System.Diagnostics.EventLog.FindSourceRegistration(string source, string machineName, bool readOnly)	Unknown
 	System.Diagnostics.EventLog.dll!System.Diagnostics.EventLog.DeleteEventSource(string source, string machineName)	Unknown
 	Log4Net.Appenders.NetCore.dll!Log4Net.Appenders.NetCore.EventLogAppender.ActivateOptions()	Unknown
 	log4net.dll!log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(System.Xml.XmlElement appenderElement)	Unknown
 	log4net.dll!log4net.Repository.Hierarchy.XmlHierarchyConfigurator.FindAppenderByReference(System.Xml.XmlElement appenderRef)	Unknown
 	log4net.dll!log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseChildrenOfLoggerElement(System.Xml.XmlElement catElement, log4net.Repository.Hierarchy.Logger log, bool isRoot)	Unknown
 	log4net.dll!log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseRoot(System.Xml.XmlElement rootElement)	Unknown
 	log4net.dll!log4net.Repository.Hierarchy.XmlHierarchyConfigurator.Configure(System.Xml.XmlElement element)	Unknown
 	log4net.dll!log4net.Repository.Hierarchy.Hierarchy.XmlRepositoryConfigure(System.Xml.XmlElement element)	Unknown
 	log4net.dll!log4net.Repository.Hierarchy.Hierarchy.log4net.Repository.IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement element)	Unknown
 	log4net.dll!log4net.Config.XmlConfigurator.InternalConfigureFromXml(log4net.Repository.ILoggerRepository repository, System.Xml.XmlElement element)	Unknown
 	log4net.dll!log4net.Config.XmlConfigurator.InternalConfigure(log4net.Repository.ILoggerRepository repository, System.IO.Stream configStream)	Unknown
 	log4net.dll!log4net.Config.XmlConfigurator.InternalConfigure(log4net.Repository.ILoggerRepository repository, System.IO.FileInfo configFile)	Unknown
 	log4net.dll!log4net.Config.XmlConfigurator.InternalConfigureAndWatch(log4net.Repository.ILoggerRepository repository, System.IO.FileInfo configFile)	Unknown
 	log4net.dll!log4net.Config.XmlConfigurator.ConfigureAndWatch(System.IO.FileInfo configFile)	Unknown
>	Log4NetTest_332.dll!Log4NetTest_332.Program.Main(string[] args) Line 15	C#

Attached is a sample project, containing the same client code for 3.4.0 and 3.3.2:

Log4NetTest.zip

I did not find anything about this change in the release notes, and at first glance I did not see the change which caused this.

So, first question is: is this change intentional or some kind of regression😄 ?

If it is intentional, I probably would have to catch this kind of error and handle it somehow.

Activity

  1. FreeAndNil commented on Sep 28, 2026

    @FreeAndNil
    Contributor

    Hi @WolfgangHG,

    thank you for the report and the sample project.

    This is an intended change, but your case was not thought about.

    In 3.4.0 OnlyOnceErrorHandler, the default error handler of every appender, writes the first error
    always. Before it did that only with log4net.Internal.Debug on. The reason: an appender could stop
    working and nobody would see it. See the 3.4.0 changelog, "report the first error of an appender
    even when log4net.Internal.Debug is off" (#310).

    ecd1b8b
    Upgrade note: previously invisible appender errors are now visible, so a misconfigured appender emits one log4net:ERROR line on stderr.

    XmlConfigurator.ConfigureAndWatch collects all internal messages and returns them. So an appender
    error is now in that list too, not only errors from the config file. Your check "list is not empty"
    is therefore stricter than before.

    LogLog.EmitInternalMessages = false does not help, it only stops the console output.
    log4net.Internal.Quiet hides every internal error, which you probably do not want.

    Filtering works. Appender errors come from OnlyOnceErrorHandler, config errors from another type:

    ICollection messages = XmlConfigurator.ConfigureAndWatch(new FileInfo("..\\..\\..\\Logger4netXML.config"));
    
    List<log4net.Util.LogLog> configErrors = messages
      .Cast<log4net.Util.LogLog>()
      .Where(m => m.Source != typeof(log4net.Util.OnlyOnceErrorHandler))
      .ToList();
    
    if (configErrors.Count > 0)
    {
      foreach (log4net.Util.LogLog x in configErrors)
      {
        Console.WriteLine(x);
      }
    }

    The appender in your stack trace is not ours, but our own EventLogAppender sends the same message.

    An appender that cannot start is a configuration problem, so its error belongs in that list.
    The filter above is the way to separate it from errors in the config file.

    Does that solve your problem?

  2. WolfgangHG commented on Sep 29, 2026

    @WolfgangHG
    Author

    @FreeAndNil Thanks for the clarification. I will implement the suggested workaround.
    It is obvious that forwarding a logger initialization error is the correct approach. Previously, the logger would have been disabled silently, which makes it hard to diagnose the missing log.

    I will close this issue if one bonus question is answered 😄:
    Thinking about the EventLogAppender, which is not available in .NET6+ applications: the workaround is to use another nuget package, but the source repository of Log4Net.Appenders.NetCore does not even exist any more. The default log4net.Appender.EventLogAppender should probably work if the log4net Nuget package contains also an assembly for the target framework net8.0-windows. But there were probably good reasons for not doing this?
    If adding another target framework is possible, I could create a new issue to follow this.

  3. FreeAndNil commented on Sep 29, 2026

    @FreeAndNil
    Contributor

    @WolfgangHG we are considering to move the Windows only Appenders into their own package (and support for modern .net).
    See #267 (#267 (reply in thread))
    Please comment on the discussion what you would like to see,

  4. WolfgangHG commented on Sep 29, 2026

    @WolfgangHG
    Author

    Thanks, Closing this one.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions