This is an automated email from the ASF dual-hosted git repository.

shunping pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 79ae776fca7 Fix PipelineOptions deserialization NPE (#38531)
79ae776fca7 is described below

commit 79ae776fca776ab57be9d8c4c50ffa9ede7e33dd
Author: Shunping Huang <[email protected]>
AuthorDate: Tue May 19 07:55:51 2026 -0400

    Fix PipelineOptions deserialization NPE (#38531)
---
 .../beam_PreCommit_Python_PVR_Flink.json           |  4 ++++
 .../beam/sdk/options/PipelineOptionsFactory.java   | 26 ++++++++++++++--------
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/.github/trigger_files/beam_PreCommit_Python_PVR_Flink.json 
b/.github/trigger_files/beam_PreCommit_Python_PVR_Flink.json
new file mode 100644
index 00000000000..616d37428c0
--- /dev/null
+++ b/.github/trigger_files/beam_PreCommit_Python_PVR_Flink.json
@@ -0,0 +1,4 @@
+{
+    "comment": "Modify this file in a trivial way to cause this test suite to 
run",
+    "revision": 1
+}
diff --git 
a/sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java
 
b/sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java
index ac76a57b6b0..b9061e1734c 100644
--- 
a/sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java
+++ 
b/sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java
@@ -502,13 +502,6 @@ public class PipelineOptionsFactory {
       new ObjectMapper()
           
.registerModules(ObjectMapper.findModules(ReflectHelpers.findClassLoader()));
 
-  private static final DefaultDeserializationContext DESERIALIZATION_CONTEXT =
-      new 
DefaultDeserializationContext.Impl(MAPPER.getDeserializationContext().getFactory())
-          .createInstance(
-              MAPPER.getDeserializationConfig(),
-              new TokenBuffer(MAPPER, false).asParser(),
-              new InjectableValues.Std());
-
   static final DefaultSerializerProvider SERIALIZER_PROVIDER =
       new DefaultSerializerProvider.Impl()
           .createInstance(MAPPER.getSerializationConfig(), 
MAPPER.getSerializerFactory());
@@ -1733,7 +1726,12 @@ public class PipelineOptionsFactory {
       BeanProperty prop = createBeanProperty(method);
       AnnotatedMember annotatedMethod = prop.getMember();
 
-      DefaultDeserializationContext context = DESERIALIZATION_CONTEXT.copy();
+      // Initialize a new context that is properly associated with a dummy 
parser.
+      // Using copy() here would leave the context's transient parser field as 
null,
+      // causing NullPointerExceptions in Jackson 2.14+ when deserializers try 
to
+      // query the parser for format constraints or coercion validations.
+      JsonParser dummyParser = new TokenBuffer(MAPPER, false).asParser();
+      DefaultDeserializationContext context = 
createDeserializationContext(dummyParser);
       Object maybeDeserializerClass =
           
context.getAnnotationIntrospector().findDeserializer(annotatedMethod);
 
@@ -1756,6 +1754,11 @@ public class PipelineOptionsFactory {
     }
   }
 
+  private static DefaultDeserializationContext 
createDeserializationContext(JsonParser parser) {
+    return ((DefaultDeserializationContext) MAPPER.getDeserializationContext())
+        .createInstance(MAPPER.getDeserializationConfig(), parser, new 
InjectableValues.Std());
+  }
+
   private static Optional<JsonSerializer<Object>> 
computeCustomSerializerForMethod(Method method) {
     try {
       BeanProperty prop = createBeanProperty(method);
@@ -1805,7 +1808,12 @@ public class PipelineOptionsFactory {
     parser.nextToken();
 
     JsonDeserializer<Object> jsonDeserializer = 
getDeserializerForMethod(method);
-    return jsonDeserializer.deserialize(parser, 
DESERIALIZATION_CONTEXT.copy());
+    // Create a fresh context that is correctly associated with the active 
parser.
+    // Using copy() here would leave the context's transient parser field as 
null,
+    // causing NullPointerExceptions in Jackson 2.14+ deserializers during 
coercion
+    // validations and length checks.
+    DefaultDeserializationContext context = 
createDeserializationContext(parser);
+    return jsonDeserializer.deserialize(parser, context);
   }
 
   /**

Reply via email to