You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sk...@apache.org on 2022/09/09 17:34:37 UTC

[ignite-3] branch main updated: IGNITE-17510 Fixed NullPointerException in cluster configuration REST calls. Fixes #1037

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

sk0x50 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 9f270fd2b4 IGNITE-17510 Fixed NullPointerException in cluster configuration REST calls. Fixes #1037
9f270fd2b4 is described below

commit 9f270fd2b498fdbbc84067267f32d65bbb2cbc7b
Author: Vadim Pakhnushev <86...@users.noreply.github.com>
AuthorDate: Fri Sep 9 20:34:23 2022 +0300

    IGNITE-17510 Fixed NullPointerException in cluster configuration REST calls. Fixes #1037
    
    Signed-off-by: Slava Koptilin <sl...@gmail.com>
---
 .../ItClusterConfigCommandNotInitializedTest.java  |  2 +-
 ...ItTopologyCommandNotInitializedClusterTest.java |  4 +-
 .../cluster/config/ClusterConfigShowCommand.java   |  6 ++-
 .../config/ClusterConfigShowReplCommand.java       |  4 +-
 .../cluster/config/ClusterConfigUpdateCommand.java |  4 ++
 .../config/ClusterConfigUpdateReplCommand.java     |  2 +
 .../commands/topology/LogicalTopologyCommand.java  |  4 ++
 .../topology/LogicalTopologyReplCommand.java       |  2 +
 ... => ClusterNotInitializedExceptionHandler.java} | 26 ++++++++---
 .../handler/IgniteCliApiExceptionHandler.java      | 13 +++---
 .../rest/ClusterManagementController.java          |  2 +-
 .../management/rest/TopologyController.java        |  2 +-
 .../ComponentNotStartedException.java}             | 13 +++---
 .../configuration/ConfigurationChanger.java        | 18 ++++++--
 .../AbstractConfigurationController.java           |  2 +-
 .../ClusterConfigurationController.java            | 21 +++++++--
 .../java/org/apache/ignite/lang/ErrorGroups.java   |  3 ++
 modules/rest-api/pom.xml                           |  8 ++++
 .../apache/ignite/internal/rest/api/Problem.java   | 11 ++---
 .../rest/api/cluster/ClusterManagementApi.java     |  7 ++-
 .../internal/rest/api/cluster/TopologyApi.java     |  3 +-
 .../api/configuration/ClusterConfigurationApi.java |  7 ++-
 .../exception/ClusterNotInitializedException.java  |  2 +-
 .../ClusterNotInitializedExceptionHandler.java     |  4 +-
 .../exception/handler/JavaExceptionHandler.java}   | 21 +++++----
 modules/rest/openapi/openapi.yaml                  | 37 +++++++++++++---
 .../rest/ItNotInitializedClusterRestTest.java      | 50 ++++++++++++++++++----
 27 files changed, 209 insertions(+), 69 deletions(-)

diff --git a/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/cluster/config/ItClusterConfigCommandNotInitializedTest.java b/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/cluster/config/ItClusterConfigCommandNotInitializedTest.java
index 072bab833c..ef41dc195f 100644
--- a/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/cluster/config/ItClusterConfigCommandNotInitializedTest.java
+++ b/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/cluster/config/ItClusterConfigCommandNotInitializedTest.java
@@ -36,7 +36,7 @@ class ItClusterConfigCommandNotInitializedTest extends CliCommandTestNotInitiali
                 this::assertOutputIsEmpty,
                 () -> assertExitCodeIs(1),
                 () -> assertErrOutputContains("Cannot show cluster config" + System.lineSeparator()
-                + "Probably, you have not initialized the cluster, try to run cluster init command")
+                + "Probably, you have not initialized the cluster, try to run ignite cluster init command")
         );
     }
 }
diff --git a/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/cluster/topology/ItTopologyCommandNotInitializedClusterTest.java b/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/cluster/topology/ItTopologyCommandNotInitializedClusterTest.java
index cb8afd4ebb..6d659ef365 100644
--- a/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/cluster/topology/ItTopologyCommandNotInitializedClusterTest.java
+++ b/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/cluster/topology/ItTopologyCommandNotInitializedClusterTest.java
@@ -52,8 +52,8 @@ class ItTopologyCommandNotInitializedClusterTest extends CliCommandTestNotInitia
         // Then prints nothing
         assertAll(
                 this::assertOutputIsEmpty,
-                () -> assertErrOutputContains(
-                        "Cluster not initialized. Call /management/v1/cluster/init in order to initialize cluster"
+                () -> assertErrOutputContains("Cannot show logical topology" + System.lineSeparator()
+                                + "Probably, you have not initialized the cluster, try to run ignite cluster init command"
                 )
         );
     }
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigShowCommand.java b/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigShowCommand.java
index 3cb1035cc8..16d42b002f 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigShowCommand.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigShowCommand.java
@@ -24,7 +24,7 @@ import org.apache.ignite.cli.call.configuration.ClusterConfigShowCallInput;
 import org.apache.ignite.cli.commands.BaseCommand;
 import org.apache.ignite.cli.commands.cluster.ClusterUrlProfileMixin;
 import org.apache.ignite.cli.core.call.CallExecutionPipeline;
-import org.apache.ignite.cli.core.exception.handler.ShowConfigExceptionHandler;
+import org.apache.ignite.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.cli.decorators.JsonDecorator;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
@@ -56,7 +56,9 @@ public class ClusterConfigShowCommand extends BaseCommand implements Callable<In
                 .output(spec.commandLine().getOut())
                 .errOutput(spec.commandLine().getErr())
                 .decorator(new JsonDecorator())
-                .exceptionHandler(new ShowConfigExceptionHandler())
+                .exceptionHandler(new ClusterNotInitializedExceptionHandler(
+                        "Cannot show cluster config", "ignite cluster init"
+                ))
                 .build()
                 .runPipeline();
     }
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigShowReplCommand.java b/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigShowReplCommand.java
index a8bfbbad3c..78194e4dde 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigShowReplCommand.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigShowReplCommand.java
@@ -23,7 +23,7 @@ import org.apache.ignite.cli.call.configuration.ClusterConfigShowCallInput;
 import org.apache.ignite.cli.commands.BaseCommand;
 import org.apache.ignite.cli.commands.cluster.ClusterUrlMixin;
 import org.apache.ignite.cli.commands.questions.ConnectToClusterQuestion;
-import org.apache.ignite.cli.core.exception.handler.ShowConfigExceptionHandler;
+import org.apache.ignite.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.cli.core.flow.Flowable;
 import org.apache.ignite.cli.core.flow.builder.Flows;
 import picocli.CommandLine.Command;
@@ -56,7 +56,7 @@ public class ClusterConfigShowReplCommand extends BaseCommand implements Runnabl
     @Override
     public void run() {
         question.askQuestionIfNotConnected(clusterUrl.getClusterUrl())
-                .exceptionHandler(new ShowConfigExceptionHandler())
+                .exceptionHandler(new ClusterNotInitializedExceptionHandler("Cannot show cluster config", "cluster init"))
                 .map(this::configShowCallInput)
                 .then(Flows.fromCall(call))
                 .toOutput(spec.commandLine().getOut(), spec.commandLine().getErr())
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigUpdateCommand.java b/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigUpdateCommand.java
index 34158838d5..855ec1458f 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigUpdateCommand.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigUpdateCommand.java
@@ -24,6 +24,7 @@ import org.apache.ignite.cli.call.configuration.ClusterConfigUpdateCallInput;
 import org.apache.ignite.cli.commands.BaseCommand;
 import org.apache.ignite.cli.commands.cluster.ClusterUrlProfileMixin;
 import org.apache.ignite.cli.core.call.CallExecutionPipeline;
+import org.apache.ignite.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
 import picocli.CommandLine.Parameters;
@@ -51,6 +52,9 @@ public class ClusterConfigUpdateCommand extends BaseCommand implements Callable<
                 .inputProvider(this::buildCallInput)
                 .output(spec.commandLine().getOut())
                 .errOutput(spec.commandLine().getErr())
+                .exceptionHandler(new ClusterNotInitializedExceptionHandler(
+                        "Cannot update cluster config", "ignite cluster init"
+                ))
                 .build()
                 .runPipeline();
     }
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigUpdateReplCommand.java b/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigUpdateReplCommand.java
index af5adb968c..db365f8be8 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigUpdateReplCommand.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/commands/cluster/config/ClusterConfigUpdateReplCommand.java
@@ -23,6 +23,7 @@ import org.apache.ignite.cli.call.configuration.ClusterConfigUpdateCallInput;
 import org.apache.ignite.cli.commands.BaseCommand;
 import org.apache.ignite.cli.commands.cluster.ClusterUrlMixin;
 import org.apache.ignite.cli.commands.questions.ConnectToClusterQuestion;
+import org.apache.ignite.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.cli.core.flow.Flowable;
 import org.apache.ignite.cli.core.flow.builder.Flows;
 import picocli.CommandLine.Command;
@@ -52,6 +53,7 @@ public class ClusterConfigUpdateReplCommand extends BaseCommand implements Runna
     @Override
     public void run() {
         question.askQuestionIfNotConnected(clusterUrl.getClusterUrl())
+                .exceptionHandler(new ClusterNotInitializedExceptionHandler("Cannot update cluster config", "cluster init"))
                 .map(this::configUpdateCallInput)
                 .then(Flows.fromCall(call))
                 .toOutput(spec.commandLine().getOut(), spec.commandLine().getErr())
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/commands/topology/LogicalTopologyCommand.java b/modules/cli/src/main/java/org/apache/ignite/cli/commands/topology/LogicalTopologyCommand.java
index d0da420c44..aca36b43c6 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/commands/topology/LogicalTopologyCommand.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/commands/topology/LogicalTopologyCommand.java
@@ -24,6 +24,7 @@ import org.apache.ignite.cli.call.cluster.topology.TopologyCallInput;
 import org.apache.ignite.cli.commands.BaseCommand;
 import org.apache.ignite.cli.commands.cluster.ClusterUrlProfileMixin;
 import org.apache.ignite.cli.core.call.CallExecutionPipeline;
+import org.apache.ignite.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.cli.decorators.TopologyDecorator;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
@@ -47,6 +48,9 @@ public class LogicalTopologyCommand extends BaseCommand implements Callable<Inte
                 .inputProvider(() -> TopologyCallInput.builder().clusterUrl(clusterUrl.getClusterUrl()).build())
                 .output(spec.commandLine().getOut())
                 .errOutput(spec.commandLine().getErr())
+                .exceptionHandler(new ClusterNotInitializedExceptionHandler(
+                        "Cannot show logical topology", "ignite cluster init"
+                ))
                 .decorator(new TopologyDecorator())
                 .build()
                 .runPipeline();
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/commands/topology/LogicalTopologyReplCommand.java b/modules/cli/src/main/java/org/apache/ignite/cli/commands/topology/LogicalTopologyReplCommand.java
index cd65340101..cc9a624a38 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/commands/topology/LogicalTopologyReplCommand.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/commands/topology/LogicalTopologyReplCommand.java
@@ -27,6 +27,7 @@ import org.apache.ignite.cli.call.cluster.topology.TopologyCallInput.TopologyCal
 import org.apache.ignite.cli.commands.BaseCommand;
 import org.apache.ignite.cli.commands.cluster.ClusterUrlMixin;
 import org.apache.ignite.cli.core.call.CallExecutionPipeline;
+import org.apache.ignite.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.cli.core.repl.Session;
 import org.apache.ignite.cli.decorators.TopologyDecorator;
 import picocli.CommandLine.Command;
@@ -66,6 +67,7 @@ public class LogicalTopologyReplCommand extends BaseCommand implements Callable<
                 .output(spec.commandLine().getOut())
                 .errOutput(spec.commandLine().getErr())
                 .decorator(new TopologyDecorator())
+                .exceptionHandler(new ClusterNotInitializedExceptionHandler("Cannot show logical topology", "cluster init"))
                 .build()
                 .runPipeline();
     }
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/ShowConfigExceptionHandler.java b/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/ClusterNotInitializedExceptionHandler.java
similarity index 69%
rename from modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/ShowConfigExceptionHandler.java
rename to modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/ClusterNotInitializedExceptionHandler.java
index ec7528067e..82ec8cdc55 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/ShowConfigExceptionHandler.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/ClusterNotInitializedExceptionHandler.java
@@ -24,20 +24,34 @@ import org.apache.ignite.cli.core.style.element.UiElements;
 import org.apache.ignite.rest.client.invoker.ApiException;
 
 /**
- * This exception handler is used only for `cluster config show` command and handles a tricky case with the 500 error on not initialized
- * cluster.
+ * This exception handler is used for cluster commands and handles a case when the cluster is not initialized.
  */
-public class ShowConfigExceptionHandler extends IgniteCliApiExceptionHandler {
+public class ClusterNotInitializedExceptionHandler extends IgniteCliApiExceptionHandler {
+    private final String header;
+
+    private final String command;
+
+    /**
+     * Constructs a new exception handler with corresponding header and command to suggest.
+     *
+     * @param header text to display as a header
+     * @param command command to suggest
+     */
+    public ClusterNotInitializedExceptionHandler(String header, String command) {
+        this.header = header;
+        this.command = command;
+    }
+
     @Override
     public int handle(ExceptionWriter err, IgniteCliApiException e) {
         if (e.getCause() instanceof ApiException) {
             ApiException apiException = (ApiException) e.getCause();
-            if (apiException.getCode() == 500) { //TODO: https://issues.apache.org/jira/browse/IGNITE-17510
+            if (apiException.getCode() == 404) {
                 err.write(
                         ErrorUiComponent.builder()
-                                .header("Cannot show cluster config")
+                                .header(header)
                                 .details("Probably, you have not initialized the cluster, try to run %s command",
-                                        UiElements.command("cluster init"))
+                                        UiElements.command(command))
                                 .build()
                                 .render()
                 );
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/IgniteCliApiExceptionHandler.java b/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/IgniteCliApiExceptionHandler.java
index 53c92517c7..12f242677c 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/IgniteCliApiExceptionHandler.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/IgniteCliApiExceptionHandler.java
@@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.net.ConnectException;
 import java.net.UnknownHostException;
+import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.ignite.cli.core.exception.ExceptionHandler;
 import org.apache.ignite.cli.core.exception.ExceptionWriter;
@@ -31,6 +32,7 @@ import org.apache.ignite.cli.core.style.element.UiElements;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.rest.client.invoker.ApiException;
+import org.apache.ignite.rest.client.model.InvalidParam;
 import org.apache.ignite.rest.client.model.Problem;
 import org.jetbrains.annotations.NotNull;
 
@@ -77,11 +79,12 @@ public class IgniteCliApiExceptionHandler implements ExceptionHandler<IgniteCliA
     private static void tryToExtractProblem(ErrorComponentBuilder errorComponentBuilder, ApiException cause) {
         try {
             Problem problem = objectMapper.readValue(cause.getResponseBody(), Problem.class);
-            if (!problem.getInvalidParams().isEmpty()) {
-                errorComponentBuilder.details(extractInvalidParams(problem));
+            List<InvalidParam> invalidParams = problem.getInvalidParams();
+            if (invalidParams != null && !invalidParams.isEmpty()) {
+                errorComponentBuilder.details(extractInvalidParams(invalidParams));
             }
             errorComponentBuilder
-                    .header(problem.getDetail())
+                    .header(problem.getDetail() != null ? problem.getDetail() : problem.getTitle())
                     .errorCode(problem.getCode())
                     .traceId(problem.getTraceId());
         } catch (JsonProcessingException ex) {
@@ -90,8 +93,8 @@ public class IgniteCliApiExceptionHandler implements ExceptionHandler<IgniteCliA
     }
 
     @NotNull
-    private static String extractInvalidParams(Problem problem) {
-        return problem.getInvalidParams().stream()
+    private static String extractInvalidParams(List<InvalidParam> invalidParams) {
+        return invalidParams.stream()
                 .map(invalidParam -> "" + invalidParam.getName() + ": " + invalidParam.getReason())
                 .collect(Collectors.joining(System.lineSeparator()));
     }
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/ClusterManagementController.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/ClusterManagementController.java
index 83aec6c4a0..3c6675a4f5 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/ClusterManagementController.java
+++ b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/ClusterManagementController.java
@@ -25,7 +25,6 @@ import java.util.concurrent.ExecutionException;
 import org.apache.ignite.internal.cluster.management.ClusterInitializer;
 import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
 import org.apache.ignite.internal.cluster.management.ClusterState;
-import org.apache.ignite.internal.cluster.management.rest.exception.ClusterNotInitializedException;
 import org.apache.ignite.internal.cluster.management.rest.exception.InvalidArgumentClusterInitializationException;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
@@ -34,6 +33,7 @@ import org.apache.ignite.internal.rest.api.cluster.ClusterStateDto;
 import org.apache.ignite.internal.rest.api.cluster.ClusterTagDto;
 import org.apache.ignite.internal.rest.api.cluster.IgniteProductVersionDto;
 import org.apache.ignite.internal.rest.api.cluster.InitCommand;
+import org.apache.ignite.internal.rest.exception.ClusterNotInitializedException;
 import org.apache.ignite.lang.IgniteException;
 import org.apache.ignite.lang.IgniteInternalException;
 
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/TopologyController.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/TopologyController.java
index 4833ffd451..91288ac759 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/TopologyController.java
+++ b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/TopologyController.java
@@ -22,10 +22,10 @@ import java.util.Collection;
 import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
-import org.apache.ignite.internal.cluster.management.rest.exception.ClusterNotInitializedException;
 import org.apache.ignite.internal.rest.api.cluster.ClusterNodeDto;
 import org.apache.ignite.internal.rest.api.cluster.NetworkAddressDto;
 import org.apache.ignite.internal.rest.api.cluster.TopologyApi;
+import org.apache.ignite.internal.rest.exception.ClusterNotInitializedException;
 import org.apache.ignite.lang.IgniteException;
 import org.apache.ignite.network.TopologyService;
 
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/ClusterNotInitializedException.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ComponentNotStartedException.java
similarity index 68%
copy from modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/ClusterNotInitializedException.java
copy to modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ComponentNotStartedException.java
index 15ba6a3dd6..f7711c8ef9 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/ClusterNotInitializedException.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ComponentNotStartedException.java
@@ -15,13 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cluster.management.rest.exception;
+package org.apache.ignite.internal.configuration;
+
+import org.apache.ignite.lang.ErrorGroups.Common;
+import org.apache.ignite.lang.IgniteInternalException;
 
 /**
- * Exception that is thrown when the cluster is not initialized.
+ * Exception thrown when component is not started.
  */
-public class ClusterNotInitializedException extends RuntimeException {
-    public ClusterNotInitializedException() {
-        super();
+public class ComponentNotStartedException extends IgniteInternalException {
+    public ComponentNotStartedException() {
+        super(Common.COMPONENT_NOT_STARTED_ERR);
     }
 }
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationChanger.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationChanger.java
index 4369df3640..056b4601f4 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationChanger.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationChanger.java
@@ -463,20 +463,32 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
      * Get storage super root.
      *
      * @return Super root storage.
+     * @throws ComponentNotStartedException if changer is not started.
      */
     public SuperRoot superRoot() {
-        return storageRoots.roots;
+        StorageRoots localRoots = storageRoots;
+
+        if (localRoots == null) {
+            throw new ComponentNotStartedException();
+        }
+
+        return localRoots.roots;
     }
 
     /**
      * Entry point for configuration changes.
      *
      * @param src Configuration source.
-     * @return fut Future that will be completed after changes are written to the storage.
+     * @return Future that will be completed after changes are written to the storage.
+     * @throws ComponentNotStartedException if changer is not started.
      */
     private CompletableFuture<Void> changeInternally(ConfigurationSource src) {
         StorageRoots localRoots = storageRoots;
 
+        if (localRoots == null) {
+            throw new ComponentNotStartedException();
+        }
+
         return storage.lastRevision()
             .thenCompose(storageRevision -> {
                 assert storageRevision != null;
@@ -503,7 +515,7 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
      * Internal configuration change method that completes provided future.
      *
      * @param src Configuration source.
-     * @return fut Future that will be completed after changes are written to the storage.
+     * @return Future that will be completed after changes are written to the storage.
      */
     private CompletableFuture<Void> changeInternally0(StorageRoots localRoots, ConfigurationSource src) {
         return CompletableFuture
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/rest/configuration/AbstractConfigurationController.java b/modules/configuration/src/main/java/org/apache/ignite/internal/rest/configuration/AbstractConfigurationController.java
index 3f580edfbb..7c1fddf800 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/rest/configuration/AbstractConfigurationController.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/rest/configuration/AbstractConfigurationController.java
@@ -40,7 +40,7 @@ public abstract class AbstractConfigurationController {
      * @return the presentation of configuration.
      */
     public String getConfiguration() {
-        return this.cfgPresentation.represent();
+        return cfgPresentation.represent();
     }
 
     /**
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/rest/configuration/ClusterConfigurationController.java b/modules/configuration/src/main/java/org/apache/ignite/internal/rest/configuration/ClusterConfigurationController.java
index 50f1621c63..4f34d0badf 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/rest/configuration/ClusterConfigurationController.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/rest/configuration/ClusterConfigurationController.java
@@ -21,8 +21,10 @@ import io.micronaut.context.annotation.Requires;
 import io.micronaut.http.annotation.Controller;
 import jakarta.inject.Named;
 import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.internal.configuration.ComponentNotStartedException;
 import org.apache.ignite.internal.configuration.rest.presentation.ConfigurationPresentation;
 import org.apache.ignite.internal.rest.api.configuration.ClusterConfigurationApi;
+import org.apache.ignite.internal.rest.exception.ClusterNotInitializedException;
 import org.apache.ignite.internal.rest.exception.handler.IgniteExceptionHandler;
 
 /**
@@ -31,7 +33,6 @@ import org.apache.ignite.internal.rest.exception.handler.IgniteExceptionHandler;
 @Controller("/management/v1/configuration/cluster/")
 @Requires(classes = IgniteExceptionHandler.class)
 public class ClusterConfigurationController extends AbstractConfigurationController implements ClusterConfigurationApi {
-
     public ClusterConfigurationController(@Named("clusterCfgPresentation") ConfigurationPresentation<String> clusterCfgPresentation) {
         super(clusterCfgPresentation);
     }
@@ -43,7 +44,11 @@ public class ClusterConfigurationController extends AbstractConfigurationControl
      */
     @Override
     public String getConfiguration() {
-        return super.getConfiguration();
+        try {
+            return super.getConfiguration();
+        } catch (ComponentNotStartedException e) {
+            throw new ClusterNotInitializedException();
+        }
     }
 
     /**
@@ -54,7 +59,11 @@ public class ClusterConfigurationController extends AbstractConfigurationControl
      */
     @Override
     public String getConfigurationByPath(String path) {
-        return super.getConfigurationByPath(path);
+        try {
+            return super.getConfigurationByPath(path);
+        } catch (ComponentNotStartedException e) {
+            throw new ClusterNotInitializedException();
+        }
     }
 
     /**
@@ -64,6 +73,10 @@ public class ClusterConfigurationController extends AbstractConfigurationControl
      */
     @Override
     public CompletableFuture<Void> updateConfiguration(String updatedConfiguration) {
-        return super.updateConfiguration(updatedConfiguration);
+        try {
+            return super.updateConfiguration(updatedConfiguration);
+        } catch (ComponentNotStartedException e) {
+            throw new ClusterNotInitializedException();
+        }
     }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
index 068e0e94b6..2c15665332 100755
--- a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
@@ -33,6 +33,9 @@ public class ErrorGroups {
         /** Node stopping error. */
         public static final int NODE_STOPPING_ERR = COMMON_ERR_GROUP.registerErrorCode(2);
 
+        /** Component not started error. */
+        public static final int COMPONENT_NOT_STARTED_ERR = COMMON_ERR_GROUP.registerErrorCode(3);
+
         /** Unknown error. */
         @Deprecated
         public static final int UNKNOWN_ERR = COMMON_ERR_GROUP.registerErrorCode(0xFFFF);
diff --git a/modules/rest-api/pom.xml b/modules/rest-api/pom.xml
index 414f65fa8a..bc26357897 100644
--- a/modules/rest-api/pom.xml
+++ b/modules/rest-api/pom.xml
@@ -73,6 +73,14 @@
             <artifactId>micronaut-http-server</artifactId>
         </dependency>
 
+        <!--
+            This is needed because micronaut-openapi generator in ignite-rest module uses these types to detect nullable properties
+        -->
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter-api</artifactId>
diff --git a/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/Problem.java b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/Problem.java
index e7c9bec2c2..9a05e8f9e3 100644
--- a/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/Problem.java
+++ b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/Problem.java
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.Collection;
 import java.util.Objects;
 import java.util.UUID;
+import javax.annotation.Nullable;
 import org.apache.ignite.internal.rest.constants.HttpCode;
 import org.apache.ignite.internal.rest.problem.Builder;
 
@@ -60,11 +61,11 @@ public class Problem {
             @JsonProperty("title") String title,
             @JsonProperty("status") int status,
             @JsonProperty("code") String code,
-            @JsonProperty("type") String type,
-            @JsonProperty("detail") String detail,
-            @JsonProperty("node") String node,
-            @JsonProperty("traceId") UUID traceId,
-            @JsonProperty("invalidParams") Collection<InvalidParam> invalidParams) {
+            @JsonProperty("type") @Nullable String type,
+            @JsonProperty("detail") @Nullable String detail,
+            @JsonProperty("node") @Nullable String node,
+            @JsonProperty("traceId") @Nullable UUID traceId,
+            @JsonProperty("invalidParams") @Nullable Collection<InvalidParam> invalidParams) {
         this.title = title;
         this.status = status;
         this.code = code;
diff --git a/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/cluster/ClusterManagementApi.java b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/cluster/ClusterManagementApi.java
index 2c5ac222b5..ea2a06506e 100644
--- a/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/cluster/ClusterManagementApi.java
+++ b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/cluster/ClusterManagementApi.java
@@ -38,16 +38,15 @@ import org.apache.ignite.internal.rest.constants.MediaType;
 @Controller("/management/v1/cluster")
 @Tag(name = "clusterManagement")
 public interface ClusterManagementApi {
-
     /**
      * Returns cluster state.
      */
     @Get("state")
     @Operation(operationId = "clusterState")
     @ApiResponse(responseCode = "200", description = "Return cluster state",
-            content = @Content(mediaType = MediaType.APPLICATION_JSON,
-                    schema = @Schema(implementation = ClusterStateDto.class)))
-    @ApiResponse(responseCode = "404", description = "Cluster state not found, it means that the cluster is not initialized")
+            content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ClusterStateDto.class)))
+    @ApiResponse(responseCode = "404", description = "Cluster state not found, it means that the cluster is not initialized",
+            content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @ApiResponse(responseCode = "500", description = "Internal error",
             content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @Produces({
diff --git a/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/cluster/TopologyApi.java b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/cluster/TopologyApi.java
index 3741ee395f..48baaf0f25 100644
--- a/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/cluster/TopologyApi.java
+++ b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/cluster/TopologyApi.java
@@ -35,7 +35,6 @@ import org.apache.ignite.internal.rest.constants.MediaType;
 @Controller("/management/v1/cluster/topology")
 @Tag(name = "topology")
 public interface TopologyApi {
-
     /**
      * Cluster physical topology.
      */
@@ -53,6 +52,8 @@ public interface TopologyApi {
     @Get("logical")
     @Operation(operationId = "logical")
     @ApiResponse(responseCode = "200", description = "Logical topology returned")
+    @ApiResponse(responseCode = "404", description = "Logical topology not found, it means that the cluster is not initialized",
+            content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @ApiResponse(responseCode = "500", description = "Internal error",
             content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @Produces(MediaType.APPLICATION_JSON)
diff --git a/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/configuration/ClusterConfigurationApi.java b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/configuration/ClusterConfigurationApi.java
index cc8ce0cf4c..7ce297e9a6 100644
--- a/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/configuration/ClusterConfigurationApi.java
+++ b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/api/configuration/ClusterConfigurationApi.java
@@ -39,7 +39,6 @@ import org.apache.ignite.internal.rest.constants.MediaType;
 @Controller("/management/v1/configuration/cluster/")
 @Tag(name = "clusterConfiguration")
 public interface ClusterConfigurationApi {
-
     /**
      * Returns cluster configuration in HOCON format. This is represented as a plain text.
      *
@@ -54,6 +53,8 @@ public interface ClusterConfigurationApi {
             content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @ApiResponse(responseCode = "400", description = "Incorrect configuration",
             content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
+    @ApiResponse(responseCode = "404", description = "Configuration not found, it means that the cluster is not initialized",
+            content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @Produces({
             MediaType.TEXT_PLAIN,
             MediaType.PROBLEM_JSON
@@ -72,6 +73,8 @@ public interface ClusterConfigurationApi {
             content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @ApiResponse(responseCode = "400", description = "Incorrect configuration",
             content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
+    @ApiResponse(responseCode = "404", description = "Configuration not found, it means that the cluster is not initialized",
+            content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @Consumes(MediaType.TEXT_PLAIN)
     @Produces(MediaType.PROBLEM_JSON)
     @Patch
@@ -91,6 +94,8 @@ public interface ClusterConfigurationApi {
             content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @ApiResponse(responseCode = "400", description = "Incorrect configuration",
             content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
+    @ApiResponse(responseCode = "404", description = "Configuration not found, it means that the cluster is not initialized",
+            content = @Content(mediaType = MediaType.PROBLEM_JSON, schema = @Schema(implementation = Problem.class)))
     @Produces({
             MediaType.TEXT_PLAIN,
             MediaType.PROBLEM_JSON
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/ClusterNotInitializedException.java b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/ClusterNotInitializedException.java
similarity index 93%
rename from modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/ClusterNotInitializedException.java
rename to modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/ClusterNotInitializedException.java
index 15ba6a3dd6..869df59fdd 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/ClusterNotInitializedException.java
+++ b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/ClusterNotInitializedException.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cluster.management.rest.exception;
+package org.apache.ignite.internal.rest.exception;
 
 /**
  * Exception that is thrown when the cluster is not initialized.
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/handler/ClusterNotInitializedExceptionHandler.java b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/handler/ClusterNotInitializedExceptionHandler.java
similarity index 91%
copy from modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/handler/ClusterNotInitializedExceptionHandler.java
copy to modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/handler/ClusterNotInitializedExceptionHandler.java
index 608fe97421..7ca77cebff 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/handler/ClusterNotInitializedExceptionHandler.java
+++ b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/handler/ClusterNotInitializedExceptionHandler.java
@@ -15,16 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cluster.management.rest.exception.handler;
+package org.apache.ignite.internal.rest.exception.handler;
 
 import io.micronaut.context.annotation.Requires;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import io.micronaut.http.server.exceptions.ExceptionHandler;
 import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cluster.management.rest.exception.ClusterNotInitializedException;
 import org.apache.ignite.internal.rest.api.Problem;
 import org.apache.ignite.internal.rest.constants.HttpCode;
+import org.apache.ignite.internal.rest.exception.ClusterNotInitializedException;
 import org.apache.ignite.internal.rest.problem.HttpProblemResponse;
 
 /**
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/handler/ClusterNotInitializedExceptionHandler.java b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/handler/JavaExceptionHandler.java
similarity index 62%
rename from modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/handler/ClusterNotInitializedExceptionHandler.java
rename to modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/handler/JavaExceptionHandler.java
index 608fe97421..a49e905409 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/rest/exception/handler/ClusterNotInitializedExceptionHandler.java
+++ b/modules/rest-api/src/main/java/org/apache/ignite/internal/rest/exception/handler/JavaExceptionHandler.java
@@ -15,31 +15,34 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cluster.management.rest.exception.handler;
+package org.apache.ignite.internal.rest.exception.handler;
 
 import io.micronaut.context.annotation.Requires;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import io.micronaut.http.server.exceptions.ExceptionHandler;
 import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cluster.management.rest.exception.ClusterNotInitializedException;
+import org.apache.ignite.internal.logger.IgniteLogger;
+import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.rest.api.Problem;
 import org.apache.ignite.internal.rest.constants.HttpCode;
 import org.apache.ignite.internal.rest.problem.HttpProblemResponse;
 
 /**
- * Handles {@link ClusterNotInitializedException} and represents it as a rest response.
+ * Handles {@link Exception} and represents it as an application/problem+json response. This will catch all unhandled exceptions since all
+ * REST endpoints are marked as producing problem json.
  */
 @Singleton
-@Requires(classes = {ClusterNotInitializedException.class, ExceptionHandler.class})
-public class ClusterNotInitializedExceptionHandler implements
-        ExceptionHandler<ClusterNotInitializedException, HttpResponse<? extends Problem>> {
+@Requires(classes = {Exception.class, ExceptionHandler.class})
+public class JavaExceptionHandler implements ExceptionHandler<Exception, HttpResponse<? extends Problem>> {
+    private static final IgniteLogger LOG = Loggers.forClass(JavaExceptionHandler.class);
 
     @Override
-    public HttpResponse<? extends Problem> handle(HttpRequest request, ClusterNotInitializedException exception) {
+    public HttpResponse<? extends Problem> handle(HttpRequest request, Exception exception) {
+        LOG.error("Unhandled exception", exception);
         return HttpProblemResponse.from(
-                Problem.fromHttpCode(HttpCode.NOT_FOUND)
-                        .detail("Cluster not initialized. Call /management/v1/cluster/init in order to initialize cluster")
+                Problem.fromHttpCode(HttpCode.INTERNAL_ERROR)
+                        .detail(exception.getMessage())
         );
     }
 }
diff --git a/modules/rest/openapi/openapi.yaml b/modules/rest/openapi/openapi.yaml
index 8a0a361ce1..c00ab0d877 100644
--- a/modules/rest/openapi/openapi.yaml
+++ b/modules/rest/openapi/openapi.yaml
@@ -55,6 +55,10 @@ paths:
         "404":
           description: "Cluster state not found, it means that the cluster is not\
             \ initialized"
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/Problem'
         "500":
           description: Internal error
           content:
@@ -76,6 +80,13 @@ paths:
                 type: array
                 items:
                   $ref: '#/components/schemas/ClusterNode'
+        "404":
+          description: "Logical topology not found, it means that the cluster is not\
+            \ initialized"
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/Problem'
         "500":
           description: Internal error
           content:
@@ -128,6 +139,13 @@ paths:
             application/problem+json:
               schema:
                 $ref: '#/components/schemas/Problem'
+        "404":
+          description: "Configuration not found, it means that the cluster is not\
+            \ initialized"
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/Problem'
     patch:
       tags:
       - clusterConfiguration
@@ -158,6 +176,13 @@ paths:
             application/problem+json:
               schema:
                 $ref: '#/components/schemas/Problem'
+        "404":
+          description: "Configuration not found, it means that the cluster is not\
+            \ initialized"
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/Problem'
   /management/v1/configuration/cluster/{path}:
     get:
       tags:
@@ -188,6 +213,13 @@ paths:
             application/problem+json:
               schema:
                 $ref: '#/components/schemas/Problem'
+        "404":
+          description: "Configuration not found, it means that the cluster is not\
+            \ initialized"
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/Problem'
   /management/v1/configuration/node:
     get:
       tags:
@@ -410,13 +442,8 @@ components:
     Problem:
       required:
       - code
-      - detail
-      - invalidParams
-      - node
       - status
       - title
-      - traceId
-      - type
       type: object
       properties:
         title:
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ItNotInitializedClusterRestTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ItNotInitializedClusterRestTest.java
index a6a97ec030..fc116beffc 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ItNotInitializedClusterRestTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ItNotInitializedClusterRestTest.java
@@ -24,14 +24,18 @@ import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertAll;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.typesafe.config.Config;
 import com.typesafe.config.ConfigFactory;
 import java.io.IOException;
 import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandlers;
+import org.apache.ignite.internal.rest.api.Problem;
 import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 /**
@@ -40,6 +44,15 @@ import org.junit.jupiter.api.extension.ExtendWith;
 @ExtendWith(WorkDirectoryExtension.class)
 public class ItNotInitializedClusterRestTest extends AbstractRestTestBase {
 
+    private ObjectMapper objectMapper;
+
+    @BeforeEach
+    @Override
+    void setUp(TestInfo testInfo) throws IOException, InterruptedException {
+        super.setUp(testInfo);
+        objectMapper = new ObjectMapper();
+    }
+
     @Test
     @DisplayName("Node configuration is available when the cluster in not initialized")
     void nodeConfiguration() throws IOException, InterruptedException {
@@ -85,10 +98,13 @@ public class ItNotInitializedClusterRestTest extends AbstractRestTestBase {
         HttpResponse<String> response = client.send(get("/management/v1/configuration/cluster"), BodyHandlers.ofString());
 
         // Expect cluster configuration is not available
-        assertThat(response.statusCode(), is(500));
-        // todo: check that human-readable problem json is returned
-        // "{\"message\":\"Internal Server Error\",\"_embedded\":{\"errors\":[{\"message\":\"Internal Server Error: null\"}]},
-        // \"_links\":{\"self\":{\"href\":\"/management/v1/configuration/cluster\",\"templated\":false}}}"
+        Problem problem = objectMapper.readValue(response.body(), Problem.class);
+        assertAll(
+                () -> assertThat(problem.status(), is(404)),
+                () -> assertThat(problem.title(), is("Not Found")),
+                () -> assertThat(problem.detail(),
+                        is("Cluster not initialized. Call /management/v1/cluster/init in order to initialize cluster"))
+        );
     }
 
     @Test
@@ -100,8 +116,14 @@ public class ItNotInitializedClusterRestTest extends AbstractRestTestBase {
                 BodyHandlers.ofString()
         );
 
-        // Expect
-        assertThat(response.statusCode(), is(500)); //todo
+        // Expect cluster configuration could not be updated
+        Problem problem = objectMapper.readValue(response.body(), Problem.class);
+        assertAll(
+                () -> assertThat(problem.status(), is(404)),
+                () -> assertThat(problem.title(), is("Not Found")),
+                () -> assertThat(problem.detail(),
+                        is("Cluster not initialized. Call /management/v1/cluster/init in order to initialize cluster"))
+        );
     }
 
     @Test
@@ -111,7 +133,13 @@ public class ItNotInitializedClusterRestTest extends AbstractRestTestBase {
         HttpResponse<String> response = client.send(get("/management/v1/cluster/topology/logical"), BodyHandlers.ofString());
 
         // Then
-        assertThat(response.statusCode(), is(404));
+        Problem problem = objectMapper.readValue(response.body(), Problem.class);
+        assertAll(
+                () -> assertThat(problem.status(), is(404)),
+                () -> assertThat(problem.title(), is("Not Found")),
+                () -> assertThat(problem.detail(),
+                        is("Cluster not initialized. Call /management/v1/cluster/init in order to initialize cluster"))
+        );
     }
 
     @Test
@@ -152,6 +180,12 @@ public class ItNotInitializedClusterRestTest extends AbstractRestTestBase {
         HttpResponse<String> response = client.send(get("/management/v1/cluster/state"), BodyHandlers.ofString());
 
         // Then
-        assertThat(response.statusCode(), is(404));
+        Problem problem = objectMapper.readValue(response.body(), Problem.class);
+        assertAll(
+                () -> assertThat(problem.status(), is(404)),
+                () -> assertThat(problem.title(), is("Not Found")),
+                () -> assertThat(problem.detail(),
+                        is("Cluster not initialized. Call /management/v1/cluster/init in order to initialize cluster"))
+        );
     }
 }