Skip to content

fix: validate Node max_retries and wait parameters#134

Open
Exploreunive wants to merge 3 commits intoThe-Pocket:mainfrom
Exploreunive:fix/node-param-validation
Open

fix: validate Node max_retries and wait parameters#134
Exploreunive wants to merge 3 commits intoThe-Pocket:mainfrom
Exploreunive:fix/node-param-validation

Conversation

@Exploreunive
Copy link
Copy Markdown

Problem

Node(max_retries=0) and Node(max_retries=-1) silently skip execution entirely — exec() is never called and None is returned, with no warning or error.

This happens because range(0) and range(-1) are empty, so the retry loop body never executes:

for self.cur_retry in range(self.max_retries):
    # This never runs when max_retries <= 0

Fix

Add validation in Node.__init__ to raise ValueError when:

  • max_retries < 1 (must be at least 1)
  • wait < 0 (must be non-negative)

Since AsyncNode inherits from Node, the validation automatically applies to all async variants (AsyncNode, AsyncBatchNode, AsyncParallelBatchNode).

Testing

  • 16 new tests in tests/test_node_params_validation.py covering:
    • ValueError for max_retries=0, -1, -100
    • ValueError for wait=-1
    • Normal operation with valid params
    • exec() is actually called (not silently skipped)
    • Retry behavior with multiple failures
    • AsyncNode validation inheritance
  • All 72 tests pass (56 existing + 16 new)

Previously, Node(max_retries=0) or Node(max_retries=-1) silently skipped
execution entirely — range(0) and range(-1) are empty, so exec() was
never called and None was returned with no warning or error.

This commit adds validation in Node.__init__ to raise ValueError when:
- max_retries < 1 (must be at least 1)
- wait < 0 (must be non-negative)

Since AsyncNode inherits from Node, the validation automatically
applies to all async variants (AsyncNode, AsyncBatchNode, etc.).

Includes 16 new tests covering:
- ValueError for max_retries=0, -1, -100
- ValueError for wait=-1
- Normal operation with valid params
- exec() is actually called with valid max_retries
…hNode

BatchNode._exec gracefully handles None via (items or []), but
AsyncBatchNode and AsyncParallelBatchNode did not, causing a TypeError
when prep_async returned None (which is the default for BaseNode.prep).

Before this fix:
  BatchNode(None)      -> [] (correct)
  AsyncBatchNode(None) -> TypeError: 'NoneType' object is not iterable

After this fix, all three batch node variants return [] when prep
returns None, maintaining consistent behavior across sync/async.

Includes 8 tests covering None, empty list, and normal data for
BatchNode, AsyncBatchNode, and AsyncParallelBatchNode.
@Exploreunive
Copy link
Copy Markdown
Author

Update: Added a second fix for a related bug.

Additional fix: handle None prep results in async batch nodes

BatchNode._exec handles None gracefully via (items or []), returning []. But AsyncBatchNode and AsyncParallelBatchNode did not, causing a TypeError: 'NoneType' object is not iterable when prep_async returned None (which is the default for BaseNode.prep).

# Before: BatchNode handles None, AsyncBatchNode crashes
BatchNode(None)      -> []  ✅
AsyncBatchNode(None) -> TypeError# After: consistent behavior
BatchNode(None)      -> []  ✅
AsyncBatchNode(None) -> []  ✅

Added 8 new tests. All 80 tests pass.

Flow.get_next_node used `if not nxt` to detect missing successors, but
this conflated 'key not found' with 'key exists but value is None'.
When users wrote `node - "end" >> None` to create a terminal branch,
returning "end" triggered a spurious warning:
  "Flow ends: 'end' not found in ['end']"

Fix: use `key not in curr.successors` to distinguish between a key
that was never registered vs a key explicitly set to None.

Fixes The-Pocket#56

Includes 4 tests covering:
- >> None with explicit action (no warning)
- Mixed >> node and >> None branches
- Unknown action still warns
- Default >> None successor
@Exploreunive
Copy link
Copy Markdown
Author

Update 2: Added a third fix for issue #56.

Fix: don't warn when >> None successor is explicitly returned

Flow.get_next_node used if not nxt to detect missing successors, but this conflated 'key not found' with 'key exists but value is None'.

When users wrote node - "end" >> None to create a terminal branch, returning "end" triggered a spurious warning:

Flow ends: 'end' not found in ['end']

Fix: Use key not in curr.successors to distinguish between a key that was never registered vs a key explicitly set to None.

Fixes #56


This PR now contains 3 fixes:

  1. Validate max_retries and wait parameters
  2. Handle None prep results in AsyncBatchNode/AsyncParallelBatchNode
  3. Don't warn on explicit >> None successors (fixes Correct pattern to terminal a flow branch? #56)

All 84 tests pass.

@Exploreunive
Copy link
Copy Markdown
Author

Update: 3rd fix added (issue #56)

Bug: Flow.get_next_node fires false warning when >> None is used to terminate a flow branch.

Root cause: if not nxt and curr.successors — uses not (truthiness check) instead of membership test. When a user writes node - "end" >> None, the successor value is None, so not nxt is True even though the key was found.

Fix: Changed to if key not in curr.successors — now correctly distinguishes between "key not registered" and "key registered with None value".

Test case from issue #56:

meta_batch - "end" >> None
# Returns "end" → no warning (correct termination)

4 new tests added. All 84 tests pass ✅

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