Skip to content

fix(validate): reject condition edges routed on the wrong port field#8

Merged
graycyrus merged 1 commit into
mainfrom
fix/b24-condition-routing-validation
Jul 13, 2026
Merged

fix(validate): reject condition edges routed on the wrong port field#8
graycyrus merged 1 commit into
mainfrom
fix/b24-condition-routing-validation

Conversation

@graycyrus

@graycyrus graycyrus commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

Bug B24 (engine hardening): a condition node's outgoing edges are routed exclusively on from_port (see engine::outgoing_by_port / handler_routing / collect_input) — to_port is never consulted to decide which successor fires. Nothing in validate::validate enforced that a condition node's edges actually declare their branch ("true"/"false") on from_port.

An edge authored with the branch label on to_port instead — e.g.

{from_node:"gate", from_port:"main", to_node:"yes", to_port:"true"}
{from_node:"gate", from_port:"main", to_node:"no",  to_port:"false"}

puts both edges into the same from_port group. handler_routing sees one port group with two targets and classifies it as a parallel HandlerRouting::FanOut — it drives both successors unconditionally, with no validation error and no routing-divergence warning. The condition gate silently becomes a no-op.

This surfaced live in OpenHuman: the workflow_builder agent produced exactly this malformed shape, and a flow sent an email even though its condition field resolved to false. See tinyhumansai/openhuman's companion fix (B23: builder prompt clarification) and B18 (null-arg hard gate) in the same investigation — this PR is B24, the engine-side hardening that gives B23 teeth regardless of how a graph was authored (agent, UI, or import).

Changes

  • src/error.rs: new ValidationError::InvalidConditionRouting { node, from_port } variant.
  • src/validate.rs: validate() now rejects any edge whose from_node is a condition node and whose from_port is not "true" or "false". A condition with only one branch wired (the common intentional gate/filter shape) is still accepted — only the value of from_port is checked, not that both are present.

Test plan

  • GGML_NATIVE=OFF cargo test --lib — all 315 tests pass (24 in validate::tests, including 4 new: accepts correct from_port shape, accepts single-branch shape, rejects the exact to_port-mislabeled bug shape, rejects an arbitrary unrecognized from_port).
  • Verified every existing condition-node test fixture in the crate (engine.rs, model/mod.rs, n8n_import via the OpenHuman host) already uses the correct from_port convention — no behavior change for correctly-authored graphs.

Summary by CodeRabbit

  • Bug Fixes
    • Added validation for condition-node connections to ensure outgoing routes use the supported true or false branch labels.
    • Invalid routing configurations now produce a clear validation error identifying the affected node and port.
    • Valid configurations, including condition nodes with only one connected branch, continue to be accepted.

B24: routing is keyed exclusively on `from_port` (see
`engine::outgoing_by_port` / `handler_routing`), but nothing in
`validate::validate` checked that a `condition` node's outgoing edges
actually emit on `from_port` "true"/"false". An edge authored with the
branch label on `to_port` instead (e.g. `{from_port:"main",
to_port:"true"}` and `{from_port:"main", to_port:"false"}`) puts both
edges in the same `from_port` group, which `handler_routing`
classifies as a parallel `FanOut` — silently driving BOTH branches
unconditionally, with no validation error or routing-divergence
warning to flag the mistake.

Add a hard structural check: every outgoing edge from a `condition`
node must have `from_port` in {"true", "false"}, or `validate` now
rejects the graph with a new `ValidationError::InvalidConditionRouting`
naming the offending node and port. A condition with only one branch
wired (a common intentional "gate/filter" shape) is still accepted.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b2ed29aa-198c-4134-852a-864dd95c5e0e

📥 Commits

Reviewing files that changed from the base of the PR and between db4165f and e8eaccb.

📒 Files selected for processing (2)
  • src/error.rs
  • src/validate.rs

📝 Walkthrough

Walkthrough

Adds structural validation for Condition node edges, requiring "true" or "false" on from_port, with a dedicated error variant and tests for valid, partial, and invalid routing shapes.

Changes

Condition routing validation

Layer / File(s) Summary
Routing error contract
src/error.rs
Adds InvalidConditionRouting with node and port details, and tests its exact display message.
Condition routing checks
src/validate.rs
Rejects outgoing condition edges with invalid from_port values while accepting valid and single-branch wiring patterns.
Estimated code review effort: 2 (Simple) ~10 minutes

Possibly related PRs

Poem

A bunny checked the branches twice,
“true” and “false” were hopping nice.
Wrong ports got turned away,
While single paths could stay.
Validation now springs bright! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main validation fix for condition-edge routing on the wrong port field.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@graycyrus graycyrus merged commit be8ae65 into main Jul 13, 2026
3 checks passed
@graycyrus graycyrus deleted the fix/b24-condition-routing-validation branch July 13, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant