diff --git a/CHANGELOG.md b/CHANGELOG.md index f9c24f5..4dc619f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `.safety-policy.yml` to document and suppress the two unfixable `ecdsa` side-channel CVEs (64396, 64459) that the upstream maintainers have acknowledged cannot be resolved in pure Python. ### Fixed +- **Add mail account wizard showed `[object Object]`** — FastAPI validation + errors return `detail` as an array of objects, not a plain string. The + frontend error handler now inspects the type of `detail`: if it is a string + it is used directly; if it is an array the individual `msg` fields are joined; + otherwise the generic `Error.message` or a fallback string is shown. The fix + is applied to both the Save and Test-Connection error paths. + - **IMAP: fix all IMAP emails appearing empty** — `aioimaplib` stores RFC822 literal data as `bytearray`, not `bytes`. The FETCH extraction loop was checking `isinstance(line, bytes)` which returns `False` for `bytearray`, diff --git a/frontend/src/components/AddMailAccountModal.tsx b/frontend/src/components/AddMailAccountModal.tsx index f4382b9..01a2211 100644 --- a/frontend/src/components/AddMailAccountModal.tsx +++ b/frontend/src/components/AddMailAccountModal.tsx @@ -116,6 +116,18 @@ export function AddMailAccountModal({ account, onClose }: AddMailAccountModalPro } }; + const extractErrorMessage = (error: unknown, fallback: string): string => { + interface FastAPIValidationError { msg: string; loc?: unknown[]; type?: string } + const detail = (error as { response?: { data?: { detail?: unknown } } })?.response?.data?.detail; + if (typeof detail === 'string') return detail; + if (Array.isArray(detail)) { + const msgs = (detail as FastAPIValidationError[]).map((d) => d?.msg ?? JSON.stringify(d)); + return msgs.join('; '); + } + if (error instanceof Error && error.message) return error.message; + return fallback; + }; + const handleTestConnection = async () => { setTestStatus('testing'); setTestMessage(''); @@ -150,10 +162,7 @@ export function AddMailAccountModal({ account, onClose }: AddMailAccountModalPro } } catch (error) { setTestStatus('error'); - const errorMessage = error instanceof Error && 'response' in error - ? (error as { response?: { data?: { detail?: string } } }).response?.data?.detail - : null; - setTestMessage(errorMessage || 'Connection failed'); + setTestMessage(extractErrorMessage(error, 'Connection failed')); } }; @@ -188,10 +197,7 @@ export function AddMailAccountModal({ account, onClose }: AddMailAccountModalPro await createMutation.mutateAsync(formData); } } catch (error) { - const errorMessage = error instanceof Error && 'response' in error - ? (error as { response?: { data?: { detail?: string } } }).response?.data?.detail - : null; - alert(errorMessage || 'Failed to save account'); + alert(extractErrorMessage(error, 'Failed to save account')); } };