fix: fix error overlay and TabErrors filtering for nested subgraphs (#9129)

## Summary

Fix error overlays not showing on subgraph container nodes and nested
error cards not appearing in the Errors tab when a node inside a
subgraph fails.

## Changes

- **What**: Error overlay and Errors tab filtering now use full
hierarchical execution IDs (e.g. `65:70`) instead of local node IDs,
enabling correct ancestor detection at any nesting depth
- Added `getExecutionIdByNode` to
[graphTraversalUtil.ts](src/utils/graphTraversalUtil.ts) to compute a
node's full execution ID chain from the root graph
- Added `errorAncestorExecutionIds` computed set and
`isContainerWithInternalError(node)` helper to
[executionErrorStore.ts](src/stores/executionErrorStore.ts) for O(1)
container checks
- Updated `hasAnyError` in
[LGraphNode.vue](src/extensions/vueNodes/components/LGraphNode.vue) to
use the new store helper
- Fixed `isErrorInSelection` in
[useErrorGroups.ts](src/components/rightSidePanel/errors/useErrorGroups.ts)
to use full execution IDs for selected containers

## Review Focus

- `errorAncestorExecutionIds` is rebuilt reactively whenever the active
errors change — confirm this is efficient enough given typical error
counts
- `getExecutionIdByNode` walks up the graph hierarchy; verify the base
case (root graph, no parent) is handled correctly

## Screenshots


https://github.com/user-attachments/assets/b5be5892-80a9-4e5e-8b6f-fe754b4ebc4e



https://github.com/user-attachments/assets/92ff12b3-3bc9-4f02-ba4a-e2c7384bafe5



https://github.com/user-attachments/assets/be8e95be-ac8c-4699-9be9-b11902294bda



┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9129-fix-fix-error-overlay-and-TabErrors-filtering-for-nested-subgraphs-3106d73d365081c1875bc1a3c89eae29)
by [Unito](https://www.unito.io)
This commit is contained in:
jaeone94
2026-02-23 19:52:45 +09:00
committed by GitHub
parent d6c902187d
commit ddcfdb924d
6 changed files with 80 additions and 16 deletions

View File

@@ -331,6 +331,35 @@ export function getNodeByExecutionId(
return targetGraph.getNodeById(localNodeId) || null
}
/**
* Returns the execution ID for a node relative to the root graph.
*
* Root-level nodes return their ID directly (e.g. "42").
* Nodes inside subgraphs return a colon-separated chain (e.g. "65:70:63").
*
* @param rootGraph - The root graph to resolve from
* @param node - The node whose execution ID to compute
* @returns The execution ID string, or null if the node has no graph
*/
export function getExecutionIdByNode(
rootGraph: LGraph,
node: LGraphNode
): NodeExecutionId | null {
if (!node.graph) return null
if (node.graph === rootGraph || node.graph.isRootGraph) {
return String(node.id)
}
const parentPath = findPartialExecutionPathToGraph(
node.graph as LGraph,
rootGraph
)
if (parentPath === undefined) return null
return `${parentPath}:${node.id}`
}
/**
* Get a node by its locator ID from anywhere in the graph hierarchy.
* Locator IDs use UUID format like "uuid:nodeId" for subgraph nodes.