Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fix execution breaks on multi/any-type slots
Bypassing a node with inputs that are not an identical match on the bypassed slot will break execution.  This includes:
- `*` ("any" types)
- INT,FLOAT (multi-types)
- Int vs INT
- 0 vs "0"

Resolved by:
- Adding a short-circuit for any types
- More explicit short-circuit for same-index matches (e.g. the third input & output)
- Preserving existing behaviour - iterate over all remaining slots, checking exact match
- Fall back to standard `isValidConnection` check - iterate over all again
  • Loading branch information
webfiltered committed Aug 9, 2025
commit 23cc8786f94e0bbda3584fa1f5f7c964493f20c8
47 changes: 40 additions & 7 deletions src/lib/litegraph/src/subgraph/ExecutableNodeDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
CallbackReturn,
ISlotType
} from '@/lib/litegraph/src/interfaces'
import { LGraphEventMode } from '@/lib/litegraph/src/litegraph'
import { LGraphEventMode, LiteGraph } from '@/lib/litegraph/src/litegraph'

import { Subgraph } from './Subgraph'
import type { SubgraphNode } from './SubgraphNode'
Expand Down Expand Up @@ -263,13 +263,8 @@ export class ExecutableNodeDTO implements ExecutableLGraphNode {

// Upstreamed: Bypass nodes are bypassed using the first input with matching type
if (this.mode === LGraphEventMode.BYPASS) {
const { inputs } = this

// Bypass nodes by finding first input with matching type
const parentInputIndexes = Object.keys(inputs).map(Number)
// Prioritise exact slot index
const indexes = [slot, ...parentInputIndexes]
const matchingIndex = indexes.find((i) => inputs[i]?.type === type)
const matchingIndex = this.#getBypassSlotIndex(slot, type)

// No input types match
if (matchingIndex === undefined) {
Expand Down Expand Up @@ -326,6 +321,44 @@ export class ExecutableNodeDTO implements ExecutableLGraphNode {
}
}

/**
* Finds the index of the input slot on this node that matches the given output {@link slot} index.
* Used when bypassing nodes.
* @param slot The output slot index on this node
* @param type The type of the final target input (so type list matches are accurate)
* @returns The index of the input slot on this node, otherwise `undefined`.
*/
#getBypassSlotIndex(slot: number, type: ISlotType) {
const { inputs } = this
const oppositeInput = inputs[slot]
const outputType = this.node.outputs[slot].type

// Any type short circuit - match slot ID, fallback to first slot
if (type === '*' || type === '') {
return inputs.length > slot ? slot : 0
}

// Prefer input with the same slot ID
if (
oppositeInput &&
LiteGraph.isValidConnection(oppositeInput.type, outputType) &&
LiteGraph.isValidConnection(oppositeInput.type, type)
) {
return slot
}

// Find first matching slot - prefer exact type
return (
// Preserve legacy behaviour; use exact match first.
inputs.findIndex((input) => input.type === type) ??
inputs.findIndex(
(input) =>
LiteGraph.isValidConnection(input.type, outputType) &&
LiteGraph.isValidConnection(input.type, type)
)
)
}

/**
* Resolves the link inside a subgraph node, from the subgraph IO node to the node inside the subgraph.
* @param slot The slot index of the output on the subgraph node.
Expand Down