From ecf8c86976d2cb52beff1b06d12663a9e5ae0583 Mon Sep 17 00:00:00 2001 From: Dread Date: Mon, 13 Jul 2026 00:12:08 -0700 Subject: [PATCH] fix: show real error text in Account Hub instead of "[object Object]" Flash GraphQL mutations return validation failures as an array of { message } objects, but every Account Hub action handler rendered them with `result.errors.join(", ")`, which String()-coerces each object to "[object Object]". This masked the actual reason on Change Level, Lock/ Activate, Update Phone, Validate Merchant, and Delete Merchant. Add a formatApiErrors() helper that extracts .message from each error object and route all five handlers through it. Plain strings and string arrays are unchanged; unexpected object shapes fall back to JSON rather than "[object Object]". Co-Authored-By: Claude Opus 4.8 --- .../page/account_hub/account_hub.js | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/admin_panel/admin_panel/page/account_hub/account_hub.js b/admin_panel/admin_panel/page/account_hub/account_hub.js index 51e33fc..ab6cf28 100644 --- a/admin_panel/admin_panel/page/account_hub/account_hub.js +++ b/admin_panel/admin_panel/page/account_hub/account_hub.js @@ -147,6 +147,22 @@ function formatCurrency(cents, currency) { return sym + (cents / 100).toFixed(2); } +function formatApiErrors(errors) { + // Flash GraphQL mutations return validation failures as an array of + // { message } objects, not strings. String()-ing them (e.g. via + // Array.join) renders "[object Object]" — pull the message out of each. + if (!errors) return ""; + const list = Array.isArray(errors) ? errors : [errors]; + return list + .map((e) => { + if (typeof e === "string") return e; + if (e && typeof e === "object") return e.message || e.error || JSON.stringify(e); + return e == null ? "" : String(e); + }) + .filter(Boolean) + .join(", "); +} + /* ───────────────────────────────────────────── AccountHub Class ───────────────────────────────────────────── */ @@ -1391,9 +1407,7 @@ class AccountHub { frappe.msgprint({ title: "Error", indicator: "red", - message: Array.isArray(result.errors) - ? result.errors.join(", ") - : result.errors, + message: formatApiErrors(result.errors), }); } else { frappe.show_alert( @@ -1462,9 +1476,7 @@ class AccountHub { frappe.msgprint({ title: "Error", indicator: "red", - message: Array.isArray(result.errors) - ? result.errors.join(", ") - : result.errors, + message: formatApiErrors(result.errors), }); } else { frappe.show_alert( @@ -1532,9 +1544,7 @@ class AccountHub { frappe.msgprint({ title: "Error", indicator: "red", - message: Array.isArray(result.errors) - ? result.errors.join(", ") - : result.errors, + message: formatApiErrors(result.errors), }); } else { frappe.show_alert( @@ -1579,9 +1589,7 @@ class AccountHub { frappe.msgprint({ title: "Error", indicator: "red", - message: Array.isArray(result.errors) - ? result.errors.join(", ") - : result.errors, + message: formatApiErrors(result.errors), }); } else { frappe.show_alert( @@ -1620,9 +1628,7 @@ class AccountHub { frappe.msgprint({ title: "Error", indicator: "red", - message: Array.isArray(result.errors) - ? result.errors.join(", ") - : result.errors, + message: formatApiErrors(result.errors), }); } else { frappe.show_alert(