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 <noreply@anthropic.com>
This commit is contained in:
parent
91a7c8ee80
commit
f462c81efb
@ -1,12 +1,41 @@
|
|||||||
const BASE = import.meta.env.VITE_API_URL ?? 'https://odoo-mcp.thedomainnest.com';
|
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<T>(path: string, opts?: RequestInit): Promise<T> {
|
async function req<T>(path: string, opts?: RequestInit): Promise<T> {
|
||||||
const res = await fetch(`${BASE}${path}`, {
|
const res = await fetch(`${BASE}${path}`, {
|
||||||
headers: { 'Content-Type': 'application/json', ...opts?.headers },
|
headers: { 'Content-Type': 'application/json', ...opts?.headers },
|
||||||
...opts,
|
...opts,
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
let data: unknown;
|
||||||
if (!res.ok) throw new Error(data.detail ?? 'Request failed');
|
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;
|
return data as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user