fix: classify wired nodes without editor x/y as regular nodes, not config nodes - #29
Merged
Merged
Conversation
…nfig nodes Node-RED's flow parser treats any node lacking both x and y properties as a global config node, regardless of its type. Hand-authored --flow-json flows (this tool's core use case, per the README's own agent example) commonly omit those editor-only coordinates, so a wired node ends up misclassified as a config node and undergoes Flow.js's circular config node dependency scan instead of normal instantiation. That scan throws "Circular config node dependency detected" the moment one of the node's own property values equals another node's id -- including its own id, e.g. when name equals id (exactly the README's agent example). This aborts the whole flow's instantiation, which previously surfaced as 'target ... is not instantiated' and made the unrelated waitForFlowsSettled() stop/safe race look like the root cause. Assign synthetic x/y coordinates to every unambiguously wired node (has a wires array, or is a link out node) before deploying an in-memory flow, leaving genuine config nodes untouched. Also add a one-tick debounce in waitForFlowsSettled() before resolving on a stop/safe runtime-state event, so a flows:started already scheduled for the same deploy attempt wins the race instead -- defensive hardening per the issue's own suggested refinement, even though current analysis shows stop/safe and flows:started are mutually exclusive outcomes in the installed @node-red/runtime version. Fixes #28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issues fixed
Closes #28
Summary
Node-RED's flow parser (
@node-red/runtime/lib/flows/util.js) classifies any node lacking bothxandyproperties as a global config node, regardless of its actualtype. Hand-authored--flow-jsonflows (this tool's core use case — see the README's ownagentexample) commonly omit those editor-only coordinates. A wired node misclassified as a config node undergoesFlow.js's config-node circular-dependency scan instead of normal instantiation, which throwsCircular config node dependency detectedthe moment one of its own property values equals another node's id — including its own id, e.g. whennameequalsid(exactly what the README's agent example does). That aborts the whole flow's instantiation, surfacing astarget ... is not instantiated, and made the unrelatedwaitForFlowsSettled()stop/safe race look like the root cause in the original bug report.Root cause confirmed by:
@node-red/runtime's parser (n.hasOwnProperty('x') && n.hasOwnProperty('y')gate) andFlow.js's circular-dependency scan@tbrandenburg/node-red-agentspackage from the issue, in a scratch dir outside the repoFix
withDeployCoordinates()insrc/run-envelope.jsassigns syntheticx/yto every node that's unambiguously wired (has awiresarray, or is alink outnode) and lacks coordinates, before building the in-memory flow storage module. Genuine config nodes (which have neither) are left untouched.waitForFlowsSettled()per the issue's own suggested refinement: astop/saferuntime-state event now defers resolution by one macrotask so an already-scheduledflows:startedfor the same deploy attempt wins instead — defensive insurance, even though analysis of the installed@node-red/runtimeshowsstop/safeandflows:startedare mutually exclusive outcomes of a single deploy attempt today.Validation
node --test test/integration/run-envelope.integration.test.js→ 3/3 pass (new issue v0.2.14 regression: flows using the agent node (node-red-agents) now deterministically fail with 'Circular config node dependency' / 'not instantiated' #28 regression test + both existing issue --docker: default ephemeral userDir silently produces empty stdout + exit 0 when target flow references a missing/unregistered node type #23 regression tests, ephemeral and persistent userDir)make ci(format + lint + fullnode --testsuite + audit) → 122/122 tests pass, lint/format clean, 0 vulnerabilitiesE2E / real-world coverage
test/integration/run-envelope.integration.test.js) reproduces the exact failure end-to-end against the real embedded Node-RED runtime using a minimal self-namedlink in -> link outflow (no mocks), and asserts a successful deploy + call.@tbrandenburg/node-red-agents@0.4.1package with the README's own documentedagentflow shape: before the fix —Error: Circular config node dependency detected: ask; after the fix — deploy succeeds and the agent node's real execution path runs.Risks / follow-ups
withDeployCoordinates()only recognizes a node as "wired" if it has awiresarray or is alink outnode. This covers 100% of this tool's supported flow shape (link in [-> ...] -> link out), but an exotic node type using neither (e.g. routing purely vialinks) would still be misclassified as a config node. Low risk given the tool's stated scope.agentexample is the literal flow shape that triggered issue v0.2.14 regression: flows using the agent node (node-red-agents) now deterministically fail with 'Circular config node dependency' / 'not instantiated' #28 — worth a maintainer look, though no README changes were made in this PR (out of scope).