fix: fail loudly when a fan-out 'items' expression does not resolve to a list#2957
fix: fail loudly when a fan-out 'items' expression does not resolve to a list#2957doquanghuy wants to merge 1 commit into
Conversation
|
@mnriem when you have a moment, would appreciate a review — happy to adjust anything. |
…o a list A non-list result from the items expression is a wiring error (the template did not resolve to a collection); silently fanning out over zero items hides it until a confusing downstream failure. Fail the step with an error naming the expression instead. An explicit empty list remains valid input. Fixes github#2956
485c977 to
317d347
Compare
There was a problem hiding this comment.
✅ Ready to approve
The change is narrowly scoped, improves correctness and debuggability, and is covered by updated and new unit tests.
Note: this review does not count toward required approvals for merging.
Pull request overview
This PR updates the workflow engine’s fan-out step to fail with a clear error when the configured items: expression does not evaluate to a list, preventing silent “zero-instance” runs caused by miswired templates (Fixes #2956).
Changes:
- Make
FanOutStep.execute()returnFAILEDwith an informative error whenitemsresolves to a non-list, while still emitting the usual output keys. - Update the existing unit test to assert the new fail-loud contract for non-list
itemsvalues. - Add a new unit test to ensure an explicitly empty list remains a valid
itemsinput and completes successfully withitem_count: 0.
File summaries
| File | Description |
|---|---|
src/specify_cli/workflows/steps/fan_out/__init__.py |
Fail-loud behavior for non-list items resolutions, preserving output shape on failure. |
tests/test_workflows.py |
Adjusts the prior test to expect failure and adds coverage for the empty-list valid case. |
Copilot's findings
- Files reviewed: 2/2 changed files
- Comments generated: 0
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Description
Fixes #2956.
FanOutStep.executesilently coerced any non-listitemsresult to[], so a mis-wired or unresolvableitems:expression produced a vacuous zero-instance run with no error anywhere near the cause. This PR makes the step fail loudly instead, with an error naming the expression and the resolved type. An explicit empty list remains valid input (legitimately-empty data still completes withitem_count: 0).The previous behavior was pinned by
test_execute_non_list_items_resolves_empty; that test is updated to the fail-loud contract, and a newtest_execute_empty_list_items_is_validlocks the empty-list-stays-valid distinction. If silent-empty was intentional for some use case, happy to rework this as an opt-in knob (allow_empty:/strict:) with fail-loud as default — see the issue for that alternative.The failure output keeps the step's four output keys (
items/max_concurrency/step_template/item_count) so downstream readers of a failed run's state don't hit missing keys.Testing
uv sync && uv run pytest— 208 passed (the new non-list test fails red against currentmain, passes with the fix; verified both directions)uvx ruff check src/— cleanuv run specify --helpAI Disclosure
Code, tests, and this description were authored with AI assistance (Claude), driven by a real-pipeline failure investigation; everything was verified by running the repo's test suite and ruff locally in both red (unfixed) and green (fixed) directions.