Found upgrading HotCRM to ObjectStack 17.0.0-rc.0 (console pinned at objectui 4a4829d0). Server contract context: action/automation business failures come back HTTP 200 with outer {success:true, data:{success:false, error}} (objectstack#3913), and flow failures have neither status nor screen.
Defect 1 — the main action path checks only the outer envelope
packages/app-shell/src/hooks/useConsoleActionRuntime.tsx:597-605 (script handler backing list toolbar / row menu / SDUI / global actions):
if (!res.ok || (json && json.success === false)) { ... } // outer only
...
return { success: true, data, reload: shouldRefresh }; // inner data.success===false lands here
→ business failure ⇒ green "Action completed successfully" toast + refresh.
The correct check already exists in the codebase — RecordDetailView.tsx:760-777 (innerFailed = inner?.success === false, with a comment naming exactly this bug). The two paths disagree; record-header actions toast red, everything else toasts green on the same failure. apiHandler (useConsoleActionRuntime.tsx:343-375) likewise inspects only res.ok.
Defect 2 — flow launch: failure falls into the terminal-success branch
useConsoleActionRuntime.tsx:479-494 (duplicated at RecordDetailView.tsx:638-656):
if (data.status === 'paused' && data.screen) { ...open FlowRunner... }
const shouldRefresh = action.refreshAfter !== false;
...
return { success: true, data: json?.data, reload: shouldRefresh }; // {success:false,error} lands HERE
A failed launch (no status, no screen) is indistinguishable from a completed flow: no dialog, spurious green toast, refresh.
Defect 3 (minor) — FlowRunner toasts the raw error value
packages/app-shell/src/views/FlowRunner.tsx:106 passes data.error to toast.error() with no string coercion, unlike errorDetail() (useConsoleActionRuntime.tsx:76-84) and the React-#31 guard in ActionRunner.ts:646-658. An object-shaped error renders nothing.
Suggested fix
Hoist the innerFailed check (and errorDetail() coercion) into useConsoleActionRuntime's script/api/flow handlers, and treat a launch/resume response lacking both status and screen with success:false as a failure before the terminal-success fallthrough.
Real-world repro: HotCRM global action log_call → "not found" swallowed, green toast; lead-conversion screen flow with a failing CRUD node → dialog closes, no error (hotcrm#524).
Found upgrading HotCRM to ObjectStack 17.0.0-rc.0 (console pinned at objectui
4a4829d0). Server contract context: action/automation business failures come back HTTP 200 with outer{success:true, data:{success:false, error}}(objectstack#3913), and flow failures have neitherstatusnorscreen.Defect 1 — the main action path checks only the outer envelope
packages/app-shell/src/hooks/useConsoleActionRuntime.tsx:597-605(script handler backing list toolbar / row menu / SDUI / global actions):→ business failure ⇒ green "Action completed successfully" toast + refresh.
The correct check already exists in the codebase —
RecordDetailView.tsx:760-777(innerFailed = inner?.success === false, with a comment naming exactly this bug). The two paths disagree; record-header actions toast red, everything else toasts green on the same failure.apiHandler(useConsoleActionRuntime.tsx:343-375) likewise inspects onlyres.ok.Defect 2 — flow launch: failure falls into the terminal-success branch
useConsoleActionRuntime.tsx:479-494(duplicated atRecordDetailView.tsx:638-656):A failed launch (no
status, noscreen) is indistinguishable from a completed flow: no dialog, spurious green toast, refresh.Defect 3 (minor) — FlowRunner toasts the raw error value
packages/app-shell/src/views/FlowRunner.tsx:106passesdata.errortotoast.error()with no string coercion, unlikeerrorDetail()(useConsoleActionRuntime.tsx:76-84) and the React-#31 guard inActionRunner.ts:646-658. An object-shaped error renders nothing.Suggested fix
Hoist the
innerFailedcheck (anderrorDetail()coercion) intouseConsoleActionRuntime's script/api/flow handlers, and treat a launch/resume response lacking bothstatusandscreenwithsuccess:falseas a failure before the terminal-success fallthrough.Real-world repro: HotCRM global action
log_call→ "not found" swallowed, green toast; lead-conversion screen flow with a failing CRUD node → dialog closes, no error (hotcrm#524).