Skip to content

LGraph.configure(data, keep_old=true) leaves _nodes_by_id stale and renumbers the configured node #15627

Description

@christian-byrne

LGraph.configure(data, keep_old = true) leaves the graph in a state where getNodeById() returns a detached node that is not in _nodes.

Repro, verified by execution:

const g = new LGraph()
g.id = createUuidv4()
const n = new LGraphNode('probe')
n.id = toNodeId(1)
g.add(n)
g.configure(g.serialize(), true)

g.getNodeById(toNodeId(1)) === n   // true — the OLD, detached node
g._nodes.includes(g.getNodeById(toNodeId(1)))   // false
g._nodes.map(x => x.id)            // ["1"] — renumbered to a string id

Root cause: configure resets this._nodes = [] (LGraph.ts:2720) but not this._nodes_by_id. The old node is therefore still registered when the replacement with the same id goes through add(), where while (!registerNodeState(this, node)) node.id = mintNodeId(state) (LGraph.ts:1171) sees a live collision and renumbers it. _nodes_by_id[1] keeps pointing at the stale object. LiteGraph logs its own "there is already a node with this ID, changing it" while this happens.

Pre-existing, not an ECS regression. I ran the merge-base arm in a separate worktree at 6532665db947acb61ed044fe91a1d4fe1fb84c8b and got the identical shape: sameObject: true, inNodes: false, ids: ["1"], same warning.

What #14246 adds on top is that the surviving renumbered node also has no layoutStore entry (_layoutRegistered === false), because configure's else detachGraphLayouts([this]) branch (LGraph.ts:2602) deletes the entries with removeLayouts: true and only the renumbered id gets re-created.

Reachability: none found. keep_old = true has zero in-repo callers other than Subgraph.configure forwarding its own parameter (LGraph.ts:2998). Across a local corpus of 29 custom-node packs / 157 frontend files, .configure(x, true) matches 0 files, 0 sites, 0 packs — control arm /registerExtension/ live at 84 of 157 files. It is a public LiteGraph API with no user I can find.

So: low priority. Filing it because it is a documented public parameter that does not work, and because "nobody calls it" is a reason to either fix it cheaply or delete it, not a reason to leave it.

git blame on LGraph.ts:2720 lands on aff7f2a296 (#8070), a 2,238-file / +612,812-line bulk import — not authorship. Leaving this unassigned rather than naming the wrong person.

Related: #15620, #15618, #15594, #15577. Found reviewing #14246 (slice C3, layout/geometry).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Potential BugUntriaged bugPublic APIAffects or interacts with the public API surface (affecting custom node or extension authors)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions