fix(designer-v2): isolate per-operation init failures so one bad op can't hang the whole load (#9223)#9338
fix(designer-v2): isolate per-operation init failures so one bad op can't hang the whole load (#9223)#9338rllyy97 wants to merge 2 commits into
Conversation
🤖 AI PR Validation ReportPR Review ResultsThank you for your submission! Here's detailed feedback on your PR title and body compliance:✅ PR Title
✅ Commit Type
|
| Section | Status | Recommendation |
|---|---|---|
| Title | ✅ | No change needed |
| Commit Type | ✅ | No change needed |
| Risk Level | ✅ | No change needed |
| What & Why | ✅ | No change needed |
| Impact of Change | ✅ | No change needed |
| Test Plan | ✅ | No change needed |
| Contributors | ✅ | No change needed |
| Screenshots/Videos | ✅ | No change needed |
Final note: The PR body is complete and compliant, and the risk level matches the change scope. The PR passes the documentation/title-body review.**
Last updated: Wed, 01 Jul 2026 22:07:15 GMT
There was a problem hiding this comment.
Pull request overview
This PR fixes a workflow-load hang in the Logic Apps Designer (DesignerV2, mirrored in designer v1) by isolating per-operation initialization failures so a single rejected init promise can’t prevent node initialization for the entire workflow.
Changes:
- Switched per-operation init aggregation from
Promise.alltoPromise.allSettledand mark only the failed node asCriticalviaupdateErrorDetails. - Wrapped
initializeConnectorOperationDetailsin try/catch to prevent unhandled rejections from connector/operation lookup calls. - Added unit tests validating graceful degradation when connector/operation lookups reject (in both
designeranddesigner-v2).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Localize/lang/strings.json | Prunes unused localized strings (auto-generated by extraction). |
| libs/designer/src/lib/core/actions/bjsworkflow/operationdeserializer.ts | Uses Promise.allSettled to avoid whole-load failure on single operation init rejection; marks failed node with critical error. |
| libs/designer/src/lib/core/actions/bjsworkflow/agent.ts | Adds guarded error handling + dispatches updateErrorDetails on connector init failures. |
| libs/designer/src/lib/core/actions/bjsworkflow/test/agent.spec.ts | Adds unit tests for connector init failure scenarios. |
| libs/designer-v2/src/lib/core/actions/bjsworkflow/operationdeserializer.ts | Same isolation behavior as designer v1 using Promise.allSettled. |
| libs/designer-v2/src/lib/core/actions/bjsworkflow/agent.ts | Same guarded connector init error handling as designer v1. |
| libs/designer-v2/src/lib/core/actions/bjsworkflow/test/agent.spec.ts | Same unit tests as designer v1 for connector init failure scenarios. |
| const error = result.reason; | ||
| const message = `Unable to initialize operation details for '${failedNodeId}'. Error details - ${parseErrorMessage(error)}`; |
There was a problem hiding this comment.
Good catch. Fixed in 330bb2f by passing a node-scoped defaultErrorMessage to parseErrorMessage, so when the error has no recognizable message field it now returns a meaningful string instead of falling through to the raw error object (which rendered as "[object Object]").
|
|
||
| return []; | ||
| } catch (error: any) { | ||
| const message = `Unable to initialize connector operation details for '${nodeId}'. Error details - ${parseErrorMessage(error)}`; |
There was a problem hiding this comment.
Good catch. Fixed in 330bb2f by passing a node-scoped defaultErrorMessage to parseErrorMessage, so when the error has no recognizable message field it now returns a meaningful string instead of falling through to the raw error object (which rendered as "[object Object]").
📊 Coverage CheckThe following changed files need attention:
Please add tests for the uncovered files before merging. |
…an't hang the whole load (#9223) initializeOperationMetadata awaited Promise.all over per-operation init calls; a single rejection (e.g. a Standard-only API like listMcpServers returning 400 for a Consumption app) prevented initializeNodes from dispatching, so every node hung on a spinner in the New Logic Apps experience (DesignerV2). Switch to Promise.allSettled and mark only the failing node with a Critical error, and wrap the previously-unguarded initializeConnectorOperationDetails in try/catch to match its sibling init functions. Scoped to designer-v2, with unit tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
28e6548 to
ead0ee0
Compare
…[object Object] parseErrorMessage falls back to returning the raw error when no message field is present, which renders as '[object Object]' in the logged/user-facing text. Provide a node-scoped default so the error message is always meaningful (addresses PR review feedback on #9223). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Commit Type
Risk Level
What & Why
Fixes #9223. In the New Logic Apps experience (DesignerV2), when a single operation-init call fails during workflow load, the entire UI hangs on an infinite spinner. The reported trigger is a Consumption Logic App where a Standard-only API (
listMcpServers) returns 400, but the failure is generic: any single per-operation init rejection blocks the whole load.Root cause:
initializeOperationMetadatainoperationdeserializer.tsawaitedPromise.all(...)over the per-operation init promises. BecausePromise.allrejects as soon as any promise rejects,initializeNodeswas never dispatched — so no nodes initialized and every node stayed stuck loading. Separately,initializeConnectorOperationDetailsinagent.tswas the only init function of its family not wrapped in try/catch, so itsgetAllConnectors()/getAgentConnectorOperation()calls could reject unguarded.Changes (scoped to
designer-v2):operationdeserializer.ts—Promise.all→Promise.allSettled. A failing operation now marks only that node with aCriticalerror viaupdateErrorDetails(and logs throughLoggerService), while all healthy nodes still aggregate and initialize normally.agent.ts— wrappedinitializeConnectorOperationDetailsin try/catch, matching the existing pattern used by its sibling init functions (...ForManagedMcpServer,...ForManifest,...ForSwagger).Scope notes: the equivalent designer v1 code is intentionally left unchanged — this fix targets the New Logic Apps experience (designer-v2) only. The specific
listMcpServersbootstrap call that awaits without a catch is Portal-side (different repo); this change removes the entire class of "one failed init hangs the whole load" from the designer-v2 load path, so a 400 (or any rejection) from a single operation no longer blocks the UI.Impact of Change
initializeOperationMetadatano longer throws on a single per-operation init rejection — failures are isolated per node.initializeConnectorOperationDetailsnow degrades gracefully instead of rejecting.Test Plan
agent.spec.ts(3 tests) indesigner-v2covering graceful degradation when connector/operation lookups reject.tsc --noEmitclean ondesigner-v2.Contributors
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com
Screenshots/Videos
N/A