Comfy-Org / Comfy-Org/ComfyUI_frontend
A chained preview exposure is dropped when its leaf shares a local node id with a sibling interior node
- Dominant language
- TypeScript
- Stars
- 2k
- Forks
- 699
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 490
Description
## Problem
When a subgraph host promotes both its own interior node and, through a nested subgraph, a node that happens to carry the same local id, the chained preview never renders. The host shows only its own.
Node ids restart at 1 in every graph, so "the host's node 3" and "a nested subgraph's node 3" are ordinary neighbours rather than a contrived case. `usePromotedPreviews.ts:156` labels each display item with the chain-resolved *leaf* id, which belongs to the nested subgraph's id space, while sibling entries use the host's own id space — the two are compared and keyed as if they were the same namespace.
## Evidence
Fixture: `Host A` (root node 1) exposes its own sampler (node 3) and, via `Nested B` (node 5), that subgraph's sampler — also numbered 3. Live preview frames driven at `1:3` and `1:5:3`:
| frames sent | previews rendered on `Host A` |
| --- | --- |
| `1:3` only | 1 |
| `1:5:3` only | **0** |
| both | **1** |
| both, control fixture with the nested leaf renumbered to 7 (`1:5:7`) | **2** |
The control isolates the shared local id as the cause: the same chain, the same exposures, the same frames — only the leaf's number differs, and it renders correctly.
The entry is lost before it reaches the renderer, not by the `v-for` key: no Vue duplicate-key warning is emitted, so `usePromotedPreviews` is emitting one entry rather than two colliding ones. I did not isolate which step of the chain resolution swallows it.
Repro is in #16654 (`browser_tests/tests/subgraph/subgraphPreviewIdentity.spec.ts`, the last two scenarios). That PR is verification-only and not for merging.
## Reachability
Colliding interior ids only survive a load with `Comfy.Graph.DeduplicateSubgraphNodeIds` set to `false`, which the repro test sets — the default-on deduplication otherwise renumbers one of them. So this is narrower than it first looks, but the setting is user-facing, and the same identifier shape is what the first-hop exclusion-set workaround in `mergeSubgraphPreviews` (added in #14569) exists to route around.
## Provenance
* **Found by:** building reproductions while reviewing #14569
* **How:** hand-built colliding-id and unique-id fixture pair, drove frames individually and together, and checked the browser console for duplicate-key warnings to rule out the render key
* **Confidence:** the behavior and its cause (shared local id) are verified by execution at `52f6404d3` with a live backend; the exact step inside chain resolution is not identified
* **Predates #14569.**
## Suggested direction
`leafExecutionId` is already computed at `usePromotedPreviews.ts:140` and discarded one line later, and `useAmbientSubgraphPreviews` likewise already holds its appended execution id. Carrying that on the display item instead of the bare leaf id — renamed accordingly — would make these identifiers unique by construction. `PromotedPreview` is runtime-only, so the persisted `previewExposures` shape is unaffected, and its only consumers are the render key in `LGraphNode.vue:166` and `mergeSubgraphPreviews`; `NodeContent` reads just `type` and `urls`.
## Related
* #14569 — introduces `mergeSubgraphPreviews`, whose first-hop exclusion set works around the same namespace mismatch from the other direction.
* #10718 — centralizing preview promotion; a natural place to settle preview identity once rather than per call site.
Contributor guide
Assessment
This issue has not been assessed yet.