Zschimmer opened a new issue, #4143:
URL: https://github.com/apache/logging-log4j2/issues/4143
## Description
When a Throwable is logged asynchronously and shortly after this changed
such that the Throwable's hashCode returns a different calculated value, a
NullPointerException is thrown in background by the asynchronous logger, and
the line is not logged.
This happen's with ScalaTest. A failing test throws a ScalaTest exception.
When the stack trace is shortened after logging, the ScalaTest exception
recalculates the hashCode based on the changed stack trace.
## Configuration
**Version:** 2.26.0
**Operating system:** macOS 26.5.1
**JDK:** 26.0.1+8-34
## Logs
```
2026-06-11T05:25:09.861732Z Log4j2-TF-1-AsyncLogger[AsyncContext@41e986c9]-1
ERROR An exception occurred processing Appender file
java.lang.NullPointerException: Cannot read field "stackTrace" because
"metadata" is null
at
org.apache.logging.log4j.core.pattern.ThrowableStackTraceRenderer.renderStackTraceElements(ThrowableStackTraceRenderer.java:151)
at
org.apache.logging.log4j.core.pattern.ThrowableStackTraceRenderer.renderThrowable(ThrowableStackTraceRenderer.java:101)
at
org.apache.logging.log4j.core.pattern.ThrowableStackTraceRenderer.renderThrowable(ThrowableStackTraceRenderer.java:77)
at
org.apache.logging.log4j.core.pattern.ThrowableStackTraceRenderer.renderThrowable(ThrowableStackTraceRenderer.java:56)
at
org.apache.logging.log4j.core.pattern.ThrowablePatternConverter.format(ThrowablePatternConverter.java:130)
at
org.apache.logging.log4j.core.layout.PatternLayout$NoFormatPatternSerializer.toSerializable(PatternLayout.java:354)
at
org.apache.logging.log4j.core.layout.PatternLayout.toText(PatternLayout.java:251)
at
org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:237)
at
org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:57)
at
org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:227)
at
org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:220)
at
org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:211)
at
org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:160)
at
org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:133)
at
org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:124)
at
org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:88)
at
org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:807)
at
org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:765)
at
org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:741)
at
org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:729)
at
org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:108)
at
org.apache.logging.log4j.core.async.AsyncLogger.actualAsyncLog(AsyncLogger.java:568)
at
org.apache.logging.log4j.core.async.RingBufferLogEvent.execute(RingBufferLogEvent.java:172)
at
org.apache.logging.log4j.core.async.RingBufferLogEventHandler4.onEvent(RingBufferLogEventHandler4.java:54)
at
org.apache.logging.log4j.core.async.RingBufferLogEventHandler.onEvent(RingBufferLogEventHandler.java:32)
at
org.apache.logging.log4j.core.async.RingBufferLogEventHandler4.onEvent(RingBufferLogEventHandler4.java:31)
at
com.lmax.disruptor.BatchEventProcessor.processEvents(BatchEventProcessor.java:168)
at
com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:125)
at java.base/java.lang.Thread.run(Thread.java:1516)
```
## Reproduction
Reproduced with Scala because the test starts log4j2 with it's own
log4j2.xml.
```
scala - <<< '
//> using dep org.apache.logging.log4j:log4j-api:2.26.0
//> using dep org.apache.logging.log4j:log4j-core:2.26.0
//> using dep org.apache.logging.log4j:log4j-slf4j2-impl:2.26.0
//> using dep com.lmax:disruptor:3.4.4
import java.lang.System.setProperty
import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file.{Files, Path}
val config =
"""<?xml version="1.0" encoding="UTF-8"?>
|<configuration status="WARN">
| <appenders>
| <randomAccessFile
| name="file"
| fileName="/tmp/TestLog4jNullPointerException.log"
| append="false"
| immediateFlush="false"/>
| </appenders>
|
| <loggers>
| <root level="trace">
| <appenderRef level="trace" ref="file"/>
| </root>
| </loggers>
|</configuration>
|""".stripMargin
final class MyException extends Exception:
private var counter = 0
override def hashCode =
counter += 1
counter
val file: Path = Files.createTempFile("TestLog4jNullPointerException-",
"xml")
try
Files.write(file, config.getBytes(UTF_8))
setProperty("log4j2.configurationFile", file.toString)
setProperty("log4j2.contextSelector",
"org.apache.logging.log4j.core.async.AsyncLoggerContextSelector")
val logger =
org.apache.logging.log4j.LogManager.getLogger("TestLog4jNullPointerException")
val exception = new MyException
logger.info("TEST", exception)
finally
Files.deleteIfExists(file)
'
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]