Skip to content

fix(workflows): fail switch step on non-mapping cases instead of crashing#3481

Open
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/switch-nondict-cases-crash
Open

fix(workflows): fail switch step on non-mapping cases instead of crashing#3481
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/switch-nondict-cases-crash

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

Summary

SwitchStep.validate() already rejects a non-mapping cases, but the engine's execute() path does not auto-validate — WorkflowEngine.load_workflow's docstring explicitly notes the returned definition is "not yet validated; call validate_workflow() or engine.validate() separately."

On such an unvalidated run, SwitchStep.execute iterated the raw value with cases.items(), so a list or scalar cases (an easy authoring mistake) raised AttributeError. The engine calls step_impl.execute() with no surrounding try/except, so that exception took down the entire run rather than failing just the step.

>>> SwitchStep().execute({"id": "sw", "expression": "x", "cases": ["a", "b"]}, ctx)
AttributeError: 'list' object has no attribute 'items'

Fix

Guard execute to return a FAILED StepResult naming the type error instead of crashing — mirroring the existing fan-out step behavior for a non-list items (test_execute_non_list_items_fails_loudly) and the "report validation errors instead of crashing" direction of #3421. The expression is still evaluated first, so its value is surfaced in the step output for downstream context.

This is the same bug class as the recent max_iterations / timeout / fan-in output guards: a validator catches the bad value, but the runtime path crashes on it when validation is skipped.

Testing

  • Added TestSwitchStep::test_execute_non_dict_cases_fails_loudly (list, str, int cases).
  • Full tests/test_workflows.py passes except the 11 pre-existing Windows symlink-guard tests, which fail identically on a clean base (require elevation on Windows).
  • ruff check clean on the changed files.

🤖 Generated with Claude Code

…hing

`SwitchStep.validate()` already rejects a non-mapping `cases`, but the
engine's `execute()` path does not auto-validate (see
`WorkflowEngine.load_workflow`, whose docstring notes the definition is
"not yet validated"). On an unvalidated run, `execute` called
`cases.items()` on the raw value, so a list or scalar `cases` authoring
mistake raised `AttributeError` and took down the whole run — the engine
invokes `step_impl.execute()` with no surrounding try/except.

Guard `execute` to return a FAILED StepResult naming the type error
instead, mirroring the fan-out step's non-list `items` handling. The
expression is still evaluated first, so its value is surfaced in the
step output for downstream context.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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