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

ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 94ee7c4138b IGNITE-27875 Handle unknown error codes (#7620)
94ee7c4138b is described below

commit 94ee7c4138bfdc77ee278b7139a5168ad56fcb3c
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Thu Feb 19 12:56:26 2026 +0200

    IGNITE-27875 Handle unknown error codes (#7620)
    
    Fix NPE on unknown error code. Unrecognized errors are now represented as 
`UNKNOWN-UNKNOWN9999-123`, where 9999 is the unknown group code.
---
 .../java/org/apache/ignite/lang/ErrorGroups.java   | 15 +++++++--
 .../apache/ignite/client/ClientComputeTest.java    | 21 ++++++++++++
 .../ignite/internal/lang/IgniteExceptionTest.java  | 39 ++++++++++++++++++++++
 .../error/code/generators/CsharpGenerator.java     |  2 +-
 .../dotnet/Apache.Ignite.Tests/ErrorGroupTests.cs  | 22 ++++++++++--
 .../platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs |  2 +-
 6 files changed, 94 insertions(+), 7 deletions(-)

diff --git a/modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java 
b/modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java
index 25a7c7048ab..eab048a4a09 100755
--- a/modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java
+++ b/modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java
@@ -35,7 +35,12 @@ import org.jetbrains.annotations.Nullable;
 public class ErrorGroups {
     /** Additional prefix that is used in a human-readable format of ignite 
errors. */
     public static final String IGNITE_ERR_PREFIX = "IGN";
+
+    /** Prefix for unknown error groups (e.g., old client gets an unknown code 
from a new server). */
+    private static final String ERR_GROUP_PREFIX_UNKNOWN = "UNKNOWN";
+
     private static final String PLACEHOLDER = "${ERROR_PREFIX}";
+
     private static final String EXCEPTION_MESSAGE_STRING_PATTERN =
             "(.*)(" + PLACEHOLDER + ")-([A-Z]+)-(\\d+)(\\s?)(.*)( 
TraceId:)([a-f0-9]{8})";
 
@@ -161,9 +166,13 @@ public class ErrorGroups {
      * @return Error Group.
      */
     public static ErrorGroup errorGroupByCode(int code) {
-        ErrorGroup grp = registeredGroups.get(extractGroupCode(code));
-        assert grp != null : "group not found, code=" + code;
-        return grp;
+        short groupCode = extractGroupCode(code);
+        ErrorGroup grp = registeredGroups.get(groupCode);
+
+        // Newer versions of Ignite may contain error codes that are not known 
to the older versions.
+        return grp == null
+                ? new ErrorGroup(ERR_GROUP_PREFIX_UNKNOWN, 
ERR_GROUP_PREFIX_UNKNOWN + groupCode, groupCode)
+                : grp;
     }
 
     /** Common error group. */
diff --git 
a/modules/client/src/test/java/org/apache/ignite/client/ClientComputeTest.java 
b/modules/client/src/test/java/org/apache/ignite/client/ClientComputeTest.java
index e184119733b..13d5110f13b 100644
--- 
a/modules/client/src/test/java/org/apache/ignite/client/ClientComputeTest.java
+++ 
b/modules/client/src/test/java/org/apache/ignite/client/ClientComputeTest.java
@@ -351,6 +351,27 @@ public class ClientComputeTest extends 
BaseIgniteAbstractTest {
         }
     }
 
+    @Test
+    void testServerReturnsUnknownErrorCode() {
+        initServers(reqId -> false);
+
+        try (var client = getClient(server1)) {
+            int customCode = (9999 << 16) | 123;
+            FakeCompute.future = CompletableFuture.failedFuture(new 
IgniteException(customCode, "Hello from a future version"));
+
+            var jobTarget = getClusterNodes("s1");
+            JobDescriptor<Object, String> jobDescriptor = 
JobDescriptor.<Object, String>builder("job").build();
+
+            IgniteException ex = assertThrows(IgniteException.class, () -> 
client.compute().execute(jobTarget, jobDescriptor, null));
+            assertThat(
+                    ex.toString(),
+                    startsWith("org.apache.ignite.lang.IgniteException: 
UNKNOWN-UNKNOWN9999-123 Hello from a future version"));
+
+            assertEquals(customCode, ex.code());
+            assertEquals("UNKNOWN-UNKNOWN9999-123", ex.codeAsString());
+        }
+    }
+
     private void initServers(Function<Integer, Boolean> shouldDropConnection) {
         ignite1 = new FakeIgnite("s1");
         ignite2 = new FakeIgnite("s2");
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/lang/IgniteExceptionTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/lang/IgniteExceptionTest.java
index 30bce9fbdae..057aaa8c61e 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/lang/IgniteExceptionTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/lang/IgniteExceptionTest.java
@@ -23,6 +23,7 @@ import static 
org.apache.ignite.lang.ErrorGroups.Common.INTERNAL_ERR;
 import static org.apache.ignite.lang.util.TraceIdUtils.getOrCreateTraceId;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.any;
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertSame;
@@ -262,6 +263,44 @@ public class IgniteExceptionTest {
         assertTrue(ex.toString().contains("IGN-CMN-65535"), ex.toString());
     }
 
+    @Test
+    public void testUnknownErrorCode() {
+        int unknownCode = (999 << 16) | 1;
+        UUID traceId = UUID.randomUUID();
+        String message = "Error from unknown group";
+
+        IgniteException ex = new IgniteException(traceId, unknownCode, 
message);
+
+        assertEquals(unknownCode, ex.code());
+        assertEquals((short) 999, ex.groupCode());
+        assertEquals((short) 1, ex.errorCode());
+        assertEquals(traceId, ex.traceId());
+        assertEquals(message, ex.getMessage());
+        assertEquals("UNKNOWN-UNKNOWN999-1", ex.codeAsString());
+        assertEquals("UNKNOWN999", ex.groupName());
+
+        assertThat(ex.toString(), containsString(message));
+        assertThat(ex.toString(), containsString("UNKNOWN-UNKNOWN999-1"));
+    }
+
+    @Test
+    public void testUnknownErrorCodeWithCause() {
+        int unknownCode = (888 << 16) | 42;
+        UUID traceId = UUID.randomUUID();
+        String message = "Another error from unknown group";
+        Throwable cause = new RuntimeException("Root cause");
+
+        IgniteException ex = new IgniteException(traceId, unknownCode, 
message, cause);
+
+        assertEquals(unknownCode, ex.code());
+        assertEquals(traceId, ex.traceId());
+        assertEquals(message, ex.getMessage());
+        assertEquals(cause, ex.getCause());
+        assertEquals("UNKNOWN-UNKNOWN888-42", ex.codeAsString());
+        assertEquals("UNKNOWN888", ex.groupName());
+        assertEquals(888, ex.groupCode());
+    }
+
     /**
      * Custom exception for tests.
      */
diff --git 
a/modules/error-code-annotation-processor/src/main/java/org/apache/ignite/internal/error/code/generators/CsharpGenerator.java
 
b/modules/error-code-annotation-processor/src/main/java/org/apache/ignite/internal/error/code/generators/CsharpGenerator.java
index ce8e2f12604..c46e2841e51 100644
--- 
a/modules/error-code-annotation-processor/src/main/java/org/apache/ignite/internal/error/code/generators/CsharpGenerator.java
+++ 
b/modules/error-code-annotation-processor/src/main/java/org/apache/ignite/internal/error/code/generators/CsharpGenerator.java
@@ -67,7 +67,7 @@ public class CsharpGenerator extends GenericGenerator {
             line("            " + descriptor.className + ".GroupCode => " + 
descriptor.className + ".GroupName,");
         }
         line();
-        line("            _ => UnknownGroupName");
+        line("            _ => UnknownGroupName + groupCode");
         line("        };");
         line();
         line("        /// <summary>");
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/ErrorGroupTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/ErrorGroupTests.cs
index e085219155e..32e51dab595 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/ErrorGroupTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/ErrorGroupTests.cs
@@ -184,8 +184,8 @@ namespace Apache.Ignite.Tests
         public void TestGetGroupNameForUnknownGroupCode()
         {
             // Newer servers may return unknown to us error codes.
-            Assert.AreEqual("UNKNOWN", ErrorGroups.GetGroupName(-1));
-            Assert.AreEqual(ErrorGroups.UnknownGroupName, 
ErrorGroups.GetGroupName(9999));
+            Assert.AreEqual("UNKNOWN-1", ErrorGroups.GetGroupName(-1));
+            Assert.AreEqual("UNKNOWN9999", ErrorGroups.GetGroupName(9999));
         }
 
         [Test]
@@ -202,6 +202,24 @@ namespace Apache.Ignite.Tests
             Assert.AreEqual("CMN", ex.GroupName);
         }
 
+        [Test]
+        public void TestUnknownErrorCode()
+        {
+            int unknownCode = (999 << 16) | 1;
+            var traceId = Guid.NewGuid();
+            string message = "Error from unknown group";
+
+            var ex = new IgniteException(traceId, unknownCode, message);
+
+            Assert.AreEqual(unknownCode, ex.Code);
+            Assert.AreEqual(999, ex.GroupCode);
+            Assert.AreEqual(1, ex.ErrorCode);
+            Assert.AreEqual(traceId, ex.TraceId);
+            Assert.AreEqual(message, ex.Message);
+            Assert.AreEqual("UNKNOWN-UNKNOWN999-1", ex.CodeAsString);
+            Assert.AreEqual("UNKNOWN999", ex.GroupName);
+        }
+
         private static IEnumerable<(short Code, string Name)> GetErrorGroups() 
=> typeof(ErrorGroups).GetNestedTypes()
                 .Select(x => ((short) 
x.GetField("GroupCode")!.GetValue(null)!, x.Name));
 
diff --git a/modules/platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs 
b/modules/platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs
index 478c47335a2..80ebf868d8d 100644
--- a/modules/platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs
@@ -54,7 +54,7 @@ namespace Apache.Ignite
             Rest.GroupCode => Rest.GroupName,
             CommonConfiguration.GroupCode => CommonConfiguration.GroupName,
 
-            _ => UnknownGroupName
+            _ => UnknownGroupName + groupCode
         };
 
         /// <summary>

Reply via email to