diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index 5c9d6ecb2..bba668908 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -47,11 +47,6 @@ :size="nodeSizes.get(nodeData.id)" :readonly="false" :executing="executionStore.executingNodeId === nodeData.id" - :error=" - executionStore.lastExecutionError?.node_id === nodeData.id - ? 'Execution error' - : null - " :zoom-level="canvasStore.canvas?.ds?.scale || 1" :data-node-id="nodeData.id" @node-click="handleNodeSelect" diff --git a/src/renderer/extensions/vueNodes/components/LGraphNode.vue b/src/renderer/extensions/vueNodes/components/LGraphNode.vue index aeb0e9a23..8844491bb 100644 --- a/src/renderer/extensions/vueNodes/components/LGraphNode.vue +++ b/src/renderer/extensions/vueNodes/components/LGraphNode.vue @@ -13,7 +13,7 @@ // border 'border border-solid border-sand-100 dark-theme:border-charcoal-300', !!executing && 'border-blue-500 dark-theme:border-blue-500', - !!(error || nodeData.hasErrors) && 'border-error', + !!hasAnyError && 'border-error', // hover 'hover:ring-7 ring-gray-500/50 dark-theme:ring-gray-500/20', // Selected @@ -21,7 +21,7 @@ !!isSelected && 'outline-black dark-theme:outline-white', !!(isSelected && executing) && 'outline-blue-500 dark-theme:outline-blue-500', - !!(isSelected && (error || nodeData.hasErrors)) && 'outline-error', + !!(isSelected && hasAnyError) && 'outline-error', { 'animate-pulse': executing, 'opacity-50': nodeData.mode === 4, @@ -134,6 +134,7 @@ import { LiteGraph } from '@/lib/litegraph/src/litegraph' import { SelectedNodeIdsKey } from '@/renderer/core/canvas/injectionKeys' import { useNodeLayout } from '@/renderer/extensions/vueNodes/layout/useNodeLayout' import { LODLevel, useLOD } from '@/renderer/extensions/vueNodes/lod/useLOD' +import { useExecutionStore } from '@/stores/executionStore' import { cn } from '@/utils/tailwindUtil' import { useVueElementTracking } from '../composables/useVueNodeResizeTracking' @@ -151,7 +152,6 @@ interface LGraphNodeProps { readonly?: boolean executing?: boolean progress?: number - error?: string | null zoomLevel?: number } @@ -176,6 +176,17 @@ const emit = defineEmits<{ useVueElementTracking(props.nodeData.id, 'node') +// Execution error state from store (direct ref access as suggested by @DrJKL) +const executionStore = useExecutionStore() +const hasExecutionError = computed( + () => executionStore.currentErrorNodeId === props.nodeData.id +) + +// Computed error states for styling +const hasAnyError = computed( + (): boolean => hasExecutionError.value || !!props.nodeData.hasErrors +) + // Inject selection state from parent const selectedNodeIds = inject(SelectedNodeIdsKey) if (!selectedNodeIds) { diff --git a/src/stores/executionStore.ts b/src/stores/executionStore.ts index 44bb13d2d..b8dc75343 100644 --- a/src/stores/executionStore.ts +++ b/src/stores/executionStore.ts @@ -407,6 +407,20 @@ export const useExecutionStore = defineStore('execution', () => { return executionId } + const lastExecutionErrorNodeLocatorId = computed(() => { + const err = lastExecutionError.value + if (!err) return null + return executionIdToNodeLocatorId(String(err.node_id)) + }) + + // Computed ref for current error node ID - components can use this directly + const currentErrorNodeId = computed(() => { + const locator = lastExecutionErrorNodeLocatorId.value + if (!locator) return null + const localId = workflowStore.nodeLocatorIdToNodeId(locator) + return localId != null ? String(localId) : null + }) + return { isIdle, clientId, @@ -426,6 +440,10 @@ export const useExecutionStore = defineStore('execution', () => { * The error from the previous execution. */ lastExecutionError, + /** + * NodeLocatorId for the most recent execution error. + */ + lastExecutionErrorNodeLocatorId, /** * The id of the node that is currently being executed (backward compatibility) */ @@ -470,6 +488,10 @@ export const useExecutionStore = defineStore('execution', () => { _executingNodeProgress, // NodeLocatorId conversion helpers executionIdToNodeLocatorId, - nodeLocatorIdToExecutionId + nodeLocatorIdToExecutionId, + /** + * The node ID that currently has an execution error (as string) + */ + currentErrorNodeId } })