This is an automated email from the ASF dual-hosted git repository. JunRuiLee pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/flink.git
commit 97af402781ef356de81c5cd4ec5156d8ab935d7a Author: Martijn Visser <[email protected]> AuthorDate: Mon Jul 13 18:56:32 2026 +0200 [FLINK-31931][runtime/rest] Return 404 instead of 500 for unknown TaskManager in TaskManagerDetailsHandler TaskManagerDetailsHandler stripped the failure from its exceptionally stage with stripExecutionException, which does not unwrap the CompletionException that a CompletableFuture reports failures with. The instanceof UnknownTaskExecutorException check therefore never matched, so a request for a gone TaskManager returned 500 with an "Unhandled exception" ERROR log instead of the intended 404. Use stripCompletionException, as the sibling TaskManager handlers already do. Generated-by: Claude Opus 4.8 (1M context) --- .../taskmanager/TaskManagerDetailsHandler.java | 2 +- .../taskmanager/TaskManagerDetailsHandlerTest.java | 27 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/rest/handler/taskmanager/TaskManagerDetailsHandler.java b/flink-runtime/src/main/java/org/apache/flink/runtime/rest/handler/taskmanager/TaskManagerDetailsHandler.java index 7acf165eeab..a0c88c4c86d 100644 --- a/flink-runtime/src/main/java/org/apache/flink/runtime/rest/handler/taskmanager/TaskManagerDetailsHandler.java +++ b/flink-runtime/src/main/java/org/apache/flink/runtime/rest/handler/taskmanager/TaskManagerDetailsHandler.java @@ -119,7 +119,7 @@ public class TaskManagerDetailsHandler .exceptionally( (Throwable throwable) -> { final Throwable strippedThrowable = - ExceptionUtils.stripExecutionException(throwable); + ExceptionUtils.stripCompletionException(throwable); if (strippedThrowable instanceof UnknownTaskExecutorException) { throw new CompletionException( diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/rest/handler/taskmanager/TaskManagerDetailsHandlerTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/rest/handler/taskmanager/TaskManagerDetailsHandlerTest.java index 5f3825b252b..c4ec69eb6b8 100644 --- a/flink-runtime/src/test/java/org/apache/flink/runtime/rest/handler/taskmanager/TaskManagerDetailsHandlerTest.java +++ b/flink-runtime/src/test/java/org/apache/flink/runtime/rest/handler/taskmanager/TaskManagerDetailsHandlerTest.java @@ -24,6 +24,7 @@ import org.apache.flink.runtime.instance.HardwareDescription; import org.apache.flink.runtime.metrics.dump.MetricDump; import org.apache.flink.runtime.metrics.dump.QueryScopeInfo; import org.apache.flink.runtime.resourcemanager.TaskManagerInfoWithSlots; +import org.apache.flink.runtime.resourcemanager.exceptions.UnknownTaskExecutorException; import org.apache.flink.runtime.resourcemanager.utils.TestingResourceManagerGateway; import org.apache.flink.runtime.rest.handler.HandlerRequest; import org.apache.flink.runtime.rest.handler.HandlerRequestException; @@ -39,10 +40,12 @@ import org.apache.flink.runtime.rest.messages.taskmanager.TaskManagerInfo; import org.apache.flink.runtime.rest.messages.taskmanager.TaskManagerMetricsInfo; import org.apache.flink.runtime.taskexecutor.TaskExecutorMemoryConfiguration; import org.apache.flink.testutils.TestingUtils; +import org.apache.flink.util.concurrent.FutureUtils; import org.apache.flink.util.jackson.JacksonMapperFactory; import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonProcessingException; import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpResponseStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -55,6 +58,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** Tests the {@link TaskManagerDetailsHandler} implementation. */ class TaskManagerDetailsHandlerTest { @@ -129,6 +133,29 @@ class TaskManagerDetailsHandlerTest { assertThat(actualJson).isEqualTo(expectedJson); } + @Test + void testUnknownTaskExecutorLeadsToNotFound() { + resourceManagerGateway.setRequestTaskManagerDetailsInfoFunction( + taskManagerId -> + FutureUtils.completedExceptionally( + new UnknownTaskExecutorException(taskManagerId))); + + assertThatThrownBy( + () -> + testInstance + .handleRequest(createRequest(), resourceManagerGateway) + .get()) + .cause() + .isInstanceOfSatisfying( + RestHandlerException.class, + restHandlerException -> { + assertThat(restHandlerException.getHttpResponseStatus()) + .isEqualTo(HttpResponseStatus.NOT_FOUND); + assertThat(restHandlerException.getMessage()) + .contains("Could not find TaskExecutor " + TASK_MANAGER_ID); + }); + } + private static void initializeMetricStore(MetricStore metricStore) { QueryScopeInfo.TaskManagerQueryScopeInfo tmScope = new QueryScopeInfo.TaskManagerQueryScopeInfo(TASK_MANAGER_ID.toString(), "Status");
