From f462c81efb12cf4d8f78fb9de7459058f4a4365e Mon Sep 17 00:00:00 2001 From: MOHAN Date: Thu, 2 Jul 2026 00:53:39 +0530 Subject: [PATCH] Fix error alerts showing "[object Object]" instead of the real message FastAPI's `detail` field is a plain string for handler-raised errors, but an array of {loc, msg, type} objects for its own automatic 422 request validation errors. new Error(detail) silently stringified that array into "[object Object]", hiding the actual validation failure from the user (e.g. when adding an Odoo connection). Normalizes both shapes into one readable message, and also guards against non-JSON error responses. Co-Authored-By: Claude Sonnet 5 --- src/lib/api.ts | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/lib/api.ts b/src/lib/api.ts index 0bd3392..de58594 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -1,12 +1,41 @@ const BASE = import.meta.env.VITE_API_URL ?? 'https://odoo-mcp.thedomainnest.com'; +// FastAPI's `detail` field is a plain string for handler-raised HTTPExceptions, +// but an array of {loc, msg, type} objects for its own automatic request +// validation errors (422s) — normalize both into one readable string instead +// of letting `new Error(x)` silently stringify an array/object into +// "[object Object]". +function errorDetailToMessage(detail: unknown): string { + if (typeof detail === 'string') return detail; + if (Array.isArray(detail)) { + return detail + .map((e) => { + if (e && typeof e === 'object' && 'msg' in e) { + const loc = Array.isArray((e as { loc?: unknown[] }).loc) + ? (e as { loc: unknown[] }).loc.filter((p) => p !== 'body').join('.') + : ''; + return loc ? `${loc}: ${(e as { msg: string }).msg}` : (e as { msg: string }).msg; + } + return String(e); + }) + .join('; '); + } + return 'Request failed'; +} + async function req(path: string, opts?: RequestInit): Promise { const res = await fetch(`${BASE}${path}`, { headers: { 'Content-Type': 'application/json', ...opts?.headers }, ...opts, }); - const data = await res.json(); - if (!res.ok) throw new Error(data.detail ?? 'Request failed'); + let data: unknown; + try { + data = await res.json(); + } catch { + if (!res.ok) throw new Error(`Request failed (HTTP ${res.status})`); + throw new Error('Server returned an unexpected (non-JSON) response.'); + } + if (!res.ok) throw new Error(errorDetailToMessage((data as { detail?: unknown })?.detail)); return data as T; }