This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch v3-2-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-2-test by this push:
new bb7c9e837ed Fix SAM login showing cryptic error on failed
authentication (#64303) (#64473)
bb7c9e837ed is described below
commit bb7c9e837ed310f9e26a5e5cbfedd55480fb3f31
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Mon Mar 30 15:08:37 2026 +0200
Fix SAM login showing cryptic error on failed authentication (#64303)
(#64473)
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.
(cherry picked from commit 6a58dd9bd387bcd8722d16c0824efe0e1d14ffce)
---
.../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 801b09ad62c..3220e25aab3 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 (OpenAPI.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: OpenAPI.BASE });
+client.setConfig({ baseURL: OpenAPI.BASE, throwOnError: true });
export const queryClient = new QueryClient({
defaultOptions: {