fix: correctly handle httpexceptions in session scope (#11542)

* Correctly handle httpexceptions in session scope

* don't assume autologin

for distributed envs, diff backends may have diff autologin
settings, so don't assume config

* [autofix.ci] apply automated fixes

* simplify conditional logic

* update comp index

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Jordan Frazier
2026-02-03 16:59:41 -05:00
committed by GitHub
parent f849047695
commit 07fa033c92
9 changed files with 656 additions and 728 deletions

View File

@ -138,9 +138,9 @@ async def auto_login(response: Response, db: DbSession):
return tokens
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
status_code=status.HTTP_403_FORBIDDEN,
detail={
"message": "Auto login is disabled. Please enable it in the settings",
"message": "Auto login is disabled.",
"auto_login": False,
},
)

View File

@ -149,7 +149,7 @@
"dependencies": [
{
"name": "apify_client",
"version": "2.4.0"
"version": "2.4.1"
},
{
"name": "langchain_community",
@ -380,7 +380,7 @@
"dependencies": [
{
"name": "apify_client",
"version": "2.4.0"
"version": "2.4.1"
},
{
"name": "langchain_community",

View File

@ -1697,7 +1697,7 @@
},
{
"name": "youtube_transcript_api",
"version": "1.2.3"
"version": "1.2.4"
},
{
"name": "lfx",

View File

@ -209,6 +209,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.28.6",
"@babel/generator": "^7.28.6",
@ -1067,6 +1068,7 @@
"resolved": "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-2.9.2.tgz",
"integrity": "sha512-To/Z92oHpIE+4nk11uVMWqo2GGRS86coeMmjxtpnErmWRdLcp1WVCVRAvn+ZwpLiNR+reWFr2FFqJRsREuZdAg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/shared-utils": "2.0.5",
"csstype": "^3.1.2",
@ -1078,6 +1080,7 @@
"resolved": "https://registry.npmjs.org/@chakra-ui/system/-/system-2.6.2.tgz",
"integrity": "sha512-EGtpoEjLrUu4W1fHD+a62XR+hzC5YfsWm+6lO0Kybcga3yYEij9beegO0jZgug27V+Rf7vns95VPVP6mFd/DEQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/color-mode": "2.2.0",
"@chakra-ui/object-utils": "2.1.0",
@ -1184,6 +1187,7 @@
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.1.tgz",
"integrity": "sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.23.0",
@ -1220,6 +1224,7 @@
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.4.tgz",
"integrity": "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@marijn/find-cluster-break": "^1.0.0"
}
@ -1229,6 +1234,7 @@
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.11.tgz",
"integrity": "sha512-bWdeR8gWM87l4DB/kYSF9A+dVackzDb/V56Tq7QVrQ7rn86W0rgZFtlL3g3pem6AeGcb9NQNoy3ao4WpW4h5tQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@codemirror/state": "^6.5.0",
"crelt": "^1.0.6",
@ -1324,6 +1330,7 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
},
@ -1347,6 +1354,7 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
}
@ -6012,6 +6020,7 @@
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@swc/counter": "^0.1.3",
"@swc/types": "^0.1.25"
@ -6372,6 +6381,7 @@
"integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
@ -7083,6 +7093,7 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz",
"integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==",
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@ -7093,6 +7104,7 @@
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"devOptional": true,
"license": "MIT",
"peer": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@ -7108,7 +7120,8 @@
"version": "1.15.9",
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.9.tgz",
"integrity": "sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/@types/stack-utils": {
"version": "2.0.3",
@ -7734,6 +7747,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -8377,6 +8391,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@ -8713,6 +8728,7 @@
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"license": "MIT",
"peer": true,
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@ -9189,6 +9205,7 @@
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
"peer": true,
"engines": {
"node": ">=12"
}
@ -9737,6 +9754,7 @@
"integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
"hasInstallScript": true,
"license": "MIT",
"peer": true,
"bin": {
"esbuild": "bin/esbuild"
},
@ -9974,6 +9992,7 @@
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.1",
@ -11608,6 +11627,7 @@
"integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@jest/core": "30.2.0",
"@jest/types": "30.2.0",
@ -13222,6 +13242,7 @@
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"license": "MIT",
"peer": true,
"bin": {
"jiti": "bin/jiti.js"
}
@ -13271,6 +13292,7 @@
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"cssstyle": "^4.2.1",
"data-urls": "^5.0.0",
@ -13310,6 +13332,7 @@
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz",
"integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 10.16.0"
}
@ -15589,6 +15612,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@ -15994,6 +16018,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@ -16066,6 +16091,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@ -16096,6 +16122,7 @@
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.1.tgz",
"integrity": "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18.0.0"
},
@ -16701,6 +16728,7 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz",
"integrity": "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/estree": "1.0.8"
},
@ -17211,7 +17239,8 @@
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz",
"integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/source-map": {
"version": "0.5.7",
@ -17331,6 +17360,7 @@
"integrity": "sha512-hgiiwT4ZWJ/yrRpoXnHpCzWOsUvLUwQqgM/ws6mCIDsKJ7Gc7irL6DjWpi8G7l1Uq5VXYsQjXQo5ydb8Pyajdg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@storybook/global": "^5.0.0",
"@storybook/icons": "^2.0.1",
@ -17780,6 +17810,7 @@
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
"integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
@ -18354,6 +18385,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -18864,6 +18896,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@ -19772,23 +19805,6 @@
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"license": "ISC"
},
"node_modules/yaml": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
"license": "ISC",
"optional": true,
"peer": true,
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
},
"funding": {
"url": "https://github.com/sponsors/eemeli"
}
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
@ -19891,6 +19907,7 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}

View File

@ -19,6 +19,10 @@ export interface AutoLoginResponse {
health_check_max_retries: number;
}
export interface AutoLoginErrorResponse {
auto_login?: boolean;
}
export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
options,
) => {
@ -33,6 +37,12 @@ export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
const retryTimerRef = useRef<NodeJS.Timeout | null>(null);
async function getAutoLoginFn(): Promise<null> {
// Skip auto-login API call if user is already authenticated (e.g., after manual login)
const currentAuthState = useAuthStore.getState();
if (currentAuthState.isAuthenticated) {
return null;
}
try {
const response = await api.get<Users>(`${getURL("AUTOLOGIN")}`);
const user = response.data;
@ -44,10 +54,13 @@ export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
resetTimer();
}
} catch (e) {
const error = e as AxiosError;
const error = e as AxiosError<AutoLoginErrorResponse>;
if (error.name !== "CanceledError") {
setAutoLogin(false);
if (!isLoginPage) {
// Don't retry if backend explicitly says auto-login is disabled
const autoLoginDisabledByBackend =
error.response?.data?.auto_login === false;
if (!isLoginPage && !autoLoginDisabledByBackend) {
await handleAutoLoginError();
}
}
@ -64,9 +77,13 @@ export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
};
const handleAutoLoginError = async () => {
// Get current state from store to avoid stale closure values
const currentAuthState = useAuthStore.getState();
const autoLoginNotAuthenticated =
(!isAuthenticated && IS_AUTO_LOGIN) ||
(!isAuthenticated && autoLogin !== undefined && autoLogin);
(!currentAuthState.isAuthenticated && IS_AUTO_LOGIN) ||
(!currentAuthState.isAuthenticated &&
currentAuthState.autoLogin !== undefined &&
currentAuthState.autoLogin);
if (autoLoginNotAuthenticated) {
const retryCount = retryCountRef.current;
@ -89,10 +106,20 @@ export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
}
};
// Determine if query should be enabled:
// - Don't run if user is already authenticated
// - Respect the enabled option from caller
// Note: We don't skip based on autoLogin === false because the frontend may
// connect to different backends with different configurations
const shouldBeEnabled = !isAuthenticated && (options?.enabled ?? true);
const queryResult = query(["useGetAutoLogin"], getAutoLoginFn, {
refetchOnWindowFocus: false,
refetchOnMount: false,
staleTime: Infinity,
retry: false,
...options,
enabled: shouldBeEnabled,
});
return queryResult;

View File

@ -28,6 +28,7 @@ export function AppInitPage() {
const setIsAuthenticated = useAuthStore((state) => state.setIsAuthenticated);
const setIsAdmin = useAuthStore((state) => state.setIsAdmin);
const autoLogin = useAuthStore((state) => state.autoLogin);
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
const { isFetched: isLoaded } = useCustomPrimaryLoading();
@ -37,11 +38,18 @@ export function AppInitPage() {
});
const { isFetched } = useGetAutoLogin({ enabled: isLoaded });
// Only fetch authenticated endpoints when user is authenticated
// (either via auto-login or manual login)
const isAuthReady = autoLogin === true || isAuthenticated;
useGetVersionQuery({ enabled: isFetched });
const { isFetched: isConfigFetched } = useGetConfig({ enabled: isFetched });
useGetGlobalVariables({ enabled: isFetched });
useGetTagsQuery({ enabled: isFetched });
useGetFoldersQuery({ enabled: isFetched });
const { isFetched: isConfigFetched } = useGetConfig({
enabled: isFetched && isAuthReady,
});
useGetGlobalVariables({ enabled: isFetched && isAuthReady });
useGetTagsQuery({ enabled: isFetched && isAuthReady });
useGetFoldersQuery({ enabled: isFetched && isAuthReady });
const { isFetched: isExamplesFetched, refetch: refetchExamples } =
useGetBasicExamplesQuery();
@ -71,17 +79,17 @@ export function AppInitPage() {
}
}, [isFetched, isConfigFetched]);
const isSessionReady = useMemo(() => {
if (autoLogin === true) {
return true;
}
if (autoLogin === false) {
return isSessionFetched;
}
return false;
}, [autoLogin, isSessionFetched]);
const isSessionReady = useMemo(
() => isAuthenticated || autoLogin || isSessionFetched,
[autoLogin, isSessionFetched, isAuthenticated],
);
const isReady = isFetched && isExamplesFetched && isSessionReady;
// Auto-login is "complete" if:
// - The query actually ran (isFetched), OR
// - We're already authenticated (so we skipped auto-login intentionally)
const isAutoLoginComplete = isFetched || isAuthenticated;
const isReady = isAutoLoginComplete && isExamplesFetched && isSessionReady;
return (
<>

View File

@ -4527,7 +4527,7 @@
},
{
"name": "anthropic",
"version": "0.76.0"
"version": "0.77.0"
}
],
"total_dependencies": 5
@ -4853,7 +4853,7 @@
"dependencies": [
{
"name": "apify_client",
"version": "2.4.0"
"version": "2.4.1"
},
{
"name": "langchain_community",
@ -67131,7 +67131,7 @@
"dependencies": [
{
"name": "numpy",
"version": "2.4.1"
"version": "2.4.2"
},
{
"name": "lfx",
@ -75977,7 +75977,7 @@
},
{
"name": "ibm_watsonx_ai",
"version": "1.5.0"
"version": "1.5.1"
},
{
"name": "langchain_ibm",
@ -97013,7 +97013,7 @@
"dependencies": [
{
"name": "numpy",
"version": "2.4.1"
"version": "2.4.2"
},
{
"name": "langchain_core",
@ -104542,7 +104542,7 @@
},
{
"name": "supabase",
"version": "2.27.2"
"version": "2.25.1"
},
{
"name": "lfx",
@ -115196,7 +115196,7 @@
},
{
"name": "youtube_transcript_api",
"version": "1.2.3"
"version": "1.2.4"
},
{
"name": "lfx",
@ -116031,6 +116031,6 @@
"num_components": 355,
"num_modules": 95
},
"sha256": "379c9fb65e43f6a3ec701a1732d6c74eef405885c5e3f5dad30f2271c6cff198",
"sha256": "934b201e21494ae6e11f223683ad79494bd716412b8ad697bbc27f0bb05d95aa",
"version": "0.3.0"
}

View File

@ -3,7 +3,6 @@
from __future__ import annotations
from contextlib import asynccontextmanager, suppress
from http import HTTPStatus
from typing import TYPE_CHECKING
from fastapi import HTTPException
@ -161,18 +160,17 @@ async def session_scope() -> AsyncGenerator[AsyncSession, None]:
try:
yield session
await session.commit()
except HTTPException:
# HTTPExceptions are control flow in FastAPI (returning 4xx/5xx responses),
# not actual errors. Don't log them - FastAPI's exception handlers will
# take care of the HTTP response. Just rollback any uncommitted changes.
if session.is_active:
with suppress(InvalidRequestError):
await session.rollback()
raise
except Exception as e:
# Log at appropriate level based on error type
if isinstance(e, HTTPException):
if HTTPStatus.BAD_REQUEST.value <= e.status_code < HTTPStatus.INTERNAL_SERVER_ERROR.value:
# Client errors (4xx) - log at info level
await logger.ainfo(f"Client error during session scope: {e.status_code}: {e.detail}")
else:
# Server errors (5xx) or other - log at error level
await logger.aexception("An error occurred during the session scope.", exception=e)
else:
# Non-HTTP exceptions - log at error level
await logger.aexception("An error occurred during the session scope.", exception=e)
# Actual application/database errors - log at error level
await logger.aexception("An error occurred during the session scope.", exception=e)
# Only rollback if session is still in a valid state
if session.is_active:

1210
uv.lock generated

File diff suppressed because it is too large Load Diff