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

dsmiley pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 0dc9b3cdc145f2a62256d0f807385093a28d11a5
Author: Serhiy Bzhezytskyy <[email protected]>
AuthorDate: Thu Jul 16 16:57:45 2026 +0300

    SOLR-3284: fix RemoteSolrException NPE when remoteError is null (#4637)
    
    A regression in Solr 10.0 for ConcurrentUpdateSolrClient
    
    (cherry picked from commit 59b23fd8f184c867e30d66e7f0eca6bb69e2d6b4)
---
 .../solr/client/solrj/RemoteSolrException.java     |  2 +-
 .../solr/client/solrj/RemoteSolrExceptionTest.java | 54 ++++++++++++++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/RemoteSolrException.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/RemoteSolrException.java
index 4552fe0cd9d..a8110be3c80 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/RemoteSolrException.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/RemoteSolrException.java
@@ -63,7 +63,7 @@ public final class RemoteSolrException extends SolrException {
   public RemoteSolrException(String remoteHost, int code, Object remoteError, 
boolean skipRetry) {
     super(ErrorCode.getErrorCode(code), "Error from server at " + remoteHost);
     this.skipRetry = skipRetry;
-    setDetails(List.of(Map.of("remoteHost", remoteHost, "remoteError", 
remoteError)));
+    setDetails(List.of(Utils.makeMap("remoteHost", remoteHost, "remoteError", 
remoteError)));
     if (remoteError != null) {
       String remoteErrorMessageSuffix = 
getRemoteErrorMessageSuffix(remoteError, "");
       if (remoteErrorMessageSuffix.length() > 2) {
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/RemoteSolrExceptionTest.java 
b/solr/solrj/src/test/org/apache/solr/client/solrj/RemoteSolrExceptionTest.java
new file mode 100644
index 00000000000..cb211e90925
--- /dev/null
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/RemoteSolrExceptionTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package org.apache.solr.client.solrj;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.solr.SolrTestCase;
+import org.junit.Test;
+
+/** Unit tests for {@link RemoteSolrException}. */
+public class RemoteSolrExceptionTest extends SolrTestCase {
+
+  /**
+   * A null remoteError must not throw: it happens whenever the server's error 
body can't be parsed
+   * (e.g. ConcurrentUpdateSolrClient passes a null error), and the 
constructor is expected to
+   * tolerate it. The consumers of the resulting exception must also tolerate 
the null.
+   */
+  @Test
+  public void testNullRemoteErrorDoesNotThrow() {
+    RemoteSolrException e = new RemoteSolrException("http://host:8983/solr";, 
500, null);
+    assertEquals(500, e.code());
+    assertNull(e.getRemoteErrorObject());
+
+    // consumers of the exception must tolerate the null remoteError entry
+    assertNotNull(e.getMessage());
+    List<Map<String, Object>> details = e.getDetails();
+    assertEquals(1, details.size());
+    assertEquals("http://host:8983/solr";, details.get(0).get("remoteHost"));
+    assertNull(details.get(0).get("remoteError"));
+  }
+
+  /** A non-null remoteError is still recorded and readable back. */
+  @Test
+  public void testRemoteErrorIsRecorded() {
+    Map<String, Object> remoteError = Map.of("msg", "boom", "code", 500);
+    RemoteSolrException e = new RemoteSolrException("http://host:8983/solr";, 
500, remoteError);
+    assertEquals(500, e.code());
+    assertEquals(remoteError, e.getRemoteErrorObject());
+  }
+}

Reply via email to