From 28192c89a5a6dd47dbec65b1cb00f4ff2e18e4e8 Mon Sep 17 00:00:00 2001 From: Ramanathan Date: Wed, 12 Aug 2026 14:51:18 +0530 Subject: [PATCH 1/2] Fix NPE in PluginElementVisitor when handling unresolved child elements --- .../PropertiesConfigurationTest.java | 26 +++++++++++++++++++ .../log4j2-unresolved-layout.properties | 26 +++++++++++++++++++ .../visitors/PluginElementVisitor.java | 4 +++ ...8_fix_plugin_element_visitor_array_npe.xml | 13 ++++++++++ 4 files changed, 69 insertions(+) create mode 100644 log4j-core-test/src/test/resources/log4j2-unresolved-layout.properties create mode 100644 src/changelog/.2.x.x/4248_fix_plugin_element_visitor_array_npe.xml diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java index e2b76e7072a..3b301f15cfb 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java @@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; import java.util.Map; @@ -32,6 +33,7 @@ import org.apache.logging.log4j.core.LifeCycle; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.ConsoleAppender; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.core.config.Property; @@ -39,6 +41,9 @@ import org.apache.logging.log4j.core.test.appender.ListAppender; import org.apache.logging.log4j.core.test.junit.LoggerContextSource; import org.apache.logging.log4j.core.test.junit.Named; +import org.apache.logging.log4j.status.StatusData; +import org.apache.logging.log4j.test.ListStatusListener; +import org.apache.logging.log4j.test.junit.UsingStatusListener; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetSystemProperty; @@ -168,4 +173,25 @@ void testLoggerLevelSysPropsAppender( final List thirdEvents = third.getEvents(); assertEquals(1, thirdEvents.size()); } + + @Test + @UsingStatusListener + @LoggerContextSource("log4j2-unresolved-layout.properties") + void testUnresolvedLayoutDoesNotFailConfiguration(final Configuration config, final ListStatusListener listener) { + assertEquals(LifeCycle.State.STARTED, config.getState()); + assertTrue( + listener.findStatusData(Level.ERROR).anyMatch(data -> data.getMessage() + .getFormattedMessage() + .contains("Unable to locate plugin for ThisLayoutDoesNotExist")), + "Unresolved layout was not reported"); + assertTrue( + listener.getStatusData() + .map(StatusData::getThrowable) + .noneMatch(NullPointerException.class::isInstance), + "Unresolved layout caused a NullPointerException"); + final Appender appender = config.getAppender("StdOut"); + assertNotNull(appender, "Appender was not created"); + assertInstanceOf(ConsoleAppender.class, appender); + assertNotNull(appender.getLayout(), "No default layout"); + } } diff --git a/log4j-core-test/src/test/resources/log4j2-unresolved-layout.properties b/log4j-core-test/src/test/resources/log4j2-unresolved-layout.properties new file mode 100644 index 00000000000..dc2f9b31a06 --- /dev/null +++ b/log4j-core-test/src/test/resources/log4j2-unresolved-layout.properties @@ -0,0 +1,26 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +status = OFF + +appender.Stdout.type = Console +appender.Stdout.name = StdOut +appender.Stdout.target = SYSTEM_OUT +appender.Stdout.layout.type = ThisLayoutDoesNotExist + +rootLogger.appenderRef.console.ref = StdOut +rootLogger.level = ERROR diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java index ef32b3737c0..198f69d04ce 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java @@ -47,6 +47,10 @@ public Object visit( boolean first = true; for (final Node child : node.getChildren()) { final PluginType childType = child.getType(); + if (childType == null) { + LOGGER.debug("Ignoring unresolved element {} in {}.", child.getName(), node.getName()); + continue; + } if (name.equalsIgnoreCase(childType.getElementName()) || this.conversionType.isAssignableFrom(childType.getPluginClass())) { if (!first) { diff --git a/src/changelog/.2.x.x/4248_fix_plugin_element_visitor_array_npe.xml b/src/changelog/.2.x.x/4248_fix_plugin_element_visitor_array_npe.xml new file mode 100644 index 00000000000..18be792b42c --- /dev/null +++ b/src/changelog/.2.x.x/4248_fix_plugin_element_visitor_array_npe.xml @@ -0,0 +1,13 @@ + + + + + + Fix `NPE` while injecting array elements of a plugin that has an unresolved child element. + + \ No newline at end of file From ddf91e3f12376248b145ee19debffc8119144f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volkan=20Yaz=C4=B1c=C4=B1?= Date: Thu, 13 Aug 2026 10:59:57 +0200 Subject: [PATCH 2/2] Change log severity to ERROR --- .../core/config/plugins/visitors/PluginElementVisitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java index 198f69d04ce..3d0b51aa7ce 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginElementVisitor.java @@ -48,7 +48,7 @@ public Object visit( for (final Node child : node.getChildren()) { final PluginType childType = child.getType(); if (childType == null) { - LOGGER.debug("Ignoring unresolved element {} in {}.", child.getName(), node.getName()); + LOGGER.error("Ignoring unresolved element {} in {}.", child.getName(), node.getName()); continue; } if (name.equalsIgnoreCase(childType.getElementName())