mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-08 14:39:58 +00:00
fix: node replacement fails after execution and modal sync (#9269)
## Summary Fixes two bugs in the node replacement flow: placeholder detection failing after workflow execution or pack reinstallation, and missing UI sync in the Errors Tab when replacements are applied from the modal dialog. ## Changes - **Placeholder detection**: Node placeholder detection now matches against `targetTypes` (derived from the replaceable node list built at workflow load time) instead of relying on `has_errors` flag or `registered_node_types` lookup. This ensures replacement works reliably after execution (where `has_errors` gets cleared) and after pack reinstallation (where the type becomes registered). - **Modal → Errors Tab sync**: Added `executionErrorStore.removeMissingNodesByType()` call in `MissingNodesContent.vue` after replacement, so the Errors Tab reflects changes immediately without requiring a page reload. ## Review Focus - `collectAllNodes` predicate change in `useNodeReplacement.ts`: now uses `targetTypes.has(originalType)` to find nodes by their original serialized type. This is independent of runtime state like `has_errors` or `registered_node_types`. - `executionErrorStore.removeMissingNodesByType` call timing in `MissingNodesContent.vue` — runs synchronously after `replaceNodesInPlace` resolves, before auto-close logic. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9269-fix-node-replacement-fails-after-execution-and-modal-sync-3146d73d365081218398c961639b450f) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -234,6 +234,7 @@ import { isCloud } from '@/platform/distribution/types'
|
||||
import type { NodeReplacement } from '@/platform/nodeReplacement/types'
|
||||
import { useNodeReplacement } from '@/platform/nodeReplacement/useNodeReplacement'
|
||||
import { useDialogStore } from '@/stores/dialogStore'
|
||||
import { useExecutionErrorStore } from '@/stores/executionErrorStore'
|
||||
import type { MissingNodeType } from '@/types/comfy'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
import { useMissingNodes } from '@/workbench/extensions/manager/composables/nodePack/useMissingNodes'
|
||||
@@ -245,6 +246,7 @@ const { missingNodeTypes } = defineProps<{
|
||||
const { missingCoreNodes } = useMissingNodes()
|
||||
const { replaceNodesInPlace } = useNodeReplacement()
|
||||
const dialogStore = useDialogStore()
|
||||
const executionErrorStore = useExecutionErrorStore()
|
||||
|
||||
interface ProcessedNode {
|
||||
label: string
|
||||
@@ -339,6 +341,14 @@ function handleReplaceSelected() {
|
||||
replacedTypes.value = nextReplaced
|
||||
selectedTypes.value = nextSelected
|
||||
|
||||
// replaceNodesInPlace() handles canvas rendering via onNodeAdded(),
|
||||
// but the modal only updates its own local UI state above.
|
||||
// Without this call the Errors Tab would still list the replaced nodes
|
||||
// as missing because executionErrorStore is not aware of the replacement.
|
||||
if (result.length > 0) {
|
||||
executionErrorStore.removeMissingNodesByType(result)
|
||||
}
|
||||
|
||||
// Auto-close when all replaceable nodes replaced and no non-replaceable remain
|
||||
const allReplaced = replaceableNodes.value.every((n) =>
|
||||
nextReplaced.has(n.label)
|
||||
|
||||
Reference in New Issue
Block a user