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

pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 6a58dd9bd38 Fix SAM login showing cryptic error on failed 
authentication (#64303)
6a58dd9bd38 is described below

commit 6a58dd9bd387bcd8722d16c0824efe0e1d14ffce
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Fri Mar 27 21:32:05 2026 +0100

    Fix SAM login showing cryptic error on failed authentication (#64303)
    
    The generated openapi client defaults to throwOnError: false, so HTTP
    errors (e.g. 401) resolve the promise instead of rejecting it.
    React Query then calls onSuccess with the error response, where
    response.data is undefined, causing a TypeError when accessing
    access_token.
    
    Add throwOnError: true to the mutate call so errors are properly
    thrown and routed to onError. Also fix ErrorAlert stale imports
    from the old code generator and update it to extract error details
    from the AxiosError response shape.
---
 .../managers/simple/ui/src/alert/ErrorAlert.tsx    | 43 +++++++++-------------
 .../simple/ui/src/queries/useCreateToken.ts        |  4 +-
 .../auth/managers/simple/ui/src/queryClient.ts     |  2 +-
 3 files changed, 21 insertions(+), 28 deletions(-)

diff --git 
a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/alert/ErrorAlert.tsx
 
b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/alert/ErrorAlert.tsx
index d17954f8106..f1214fc05f8 100644
--- 
a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/alert/ErrorAlert.tsx
+++ 
b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/alert/ErrorAlert.tsx
@@ -17,47 +17,40 @@
  * under the License.
  */
 import { HStack } from "@chakra-ui/react";
-import type { ApiError } from "openapi-gen/requests/core/ApiError";
-import type { HTTPExceptionResponse, HTTPValidationError } from 
"openapi-gen/requests/types.gen";
+import type { AxiosError } from "axios";
+import type { HttpExceptionResponse, HttpValidationError } from 
"openapi/requests/types.gen";
 
 import { Alert } from "./Alert";
 
-type ExpandedApiError = {
-  body: HTTPExceptionResponse | HTTPValidationError | undefined;
-} & ApiError;
-
 type Props = {
   readonly error?: unknown;
 };
 
 export const ErrorAlert = ({ error: err }: Props) => {
-  const error = err as ExpandedApiError;
-
-  if (!Boolean(error)) {
+  if (err === undefined || err === null) {
     return undefined;
   }
 
-  const details = error.body?.detail;
-  let detailMessage;
-
-  if (details !== undefined) {
-    if (typeof details === "string") {
-      detailMessage = details;
-    } else if (Array.isArray(details)) {
-      detailMessage = details.map(
-        (detail) => `
-          ${detail.loc.join(".")} ${detail.msg}`,
-      );
-    } else {
-      detailMessage = Object.keys(details).map((key) => `${key}: 
${details[key] as string}`);
-    }
+  const error = err as AxiosError<HttpExceptionResponse | HttpValidationError>;
+  const { message, response } = error;
+  const statusCode = response?.status;
+  const statusText = response?.statusText ?? message;
+  const detail = response?.data.detail;
+  let detailMessage: React.ReactNode;
+
+  if (typeof detail === "string") {
+    detailMessage = detail;
+  } else if (Array.isArray(detail)) {
+    detailMessage = detail.map((entry) => `${entry.loc.join(".")} 
${entry.msg}`).join(", ");
   }
 
   return (
     <Alert status="error">
       <HStack align="start" flexDirection="column" gap={2} mt={-1}>
-        {error.status} {error.message}
-        {detailMessage === error.message ? undefined : 
<span>{detailMessage}</span>}
+        {statusCode} {statusText}
+        {detailMessage !== undefined && detailMessage !== statusText ? (
+          <span>{detailMessage}</span>
+        ) : undefined}
       </HStack>
     </Alert>
   );
diff --git 
a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queries/useCreateToken.ts
 
b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queries/useCreateToken.ts
index b3c77263f4a..b3dba0f66bb 100644
--- 
a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queries/useCreateToken.ts
+++ 
b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queries/useCreateToken.ts
@@ -32,8 +32,8 @@ export const useCreateToken = ({ onSuccess }: { onSuccess: 
(data: LoginResponse)
   const { isPending, mutate } = useCreateTokenMutation(undefined, {
     onError,
     onSuccess: (response) => {
-      onSuccess(response.data);
-  },
+      onSuccess(response.data as LoginResponse);
+    },
   });
 
   const createToken = (variableRequestBody: LoginBody) => {
diff --git 
a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queryClient.ts
 
b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queryClient.ts
index 51791c7897f..87ca13a529c 100644
--- 
a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queryClient.ts
+++ 
b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/src/queryClient.ts
@@ -29,7 +29,7 @@ if (base.endsWith("/")) {
 
 // Configure the generated API client so requests include the subpath prefix
 // when Airflow runs behind a reverse proxy (e.g. /team-a/auth/token instead 
of /auth/token).
-client.setConfig({ baseURL: base });
+client.setConfig({ baseURL: base, throwOnError: true });
 
 export const queryClient = new QueryClient({
   defaultOptions: {

Reply via email to