deepset-ai / deepset-ai/haystack
ConditionalRouter silently coerces string output to another type when output_type is `str | None`
@sjrl is already working on this.
Since Sep 5, 2026.
- Dominant language
- Python
- Stars
- 26.6k
- Forks
- 3.2k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 194
Description
Describe the bug
ConditionalRouter.run() skips ast.literal_eval coercion when output_type is exactly str, but not when output_type is a Union that includes str (e.g. str | None, Optional[str]). This means a perfectly normal "optional string output" declaration silently has its string value mangled if the rendered value happens to parse as a Python literal.
Affected code
haystack/components/routers/conditional_router.py, inside run():
with contextlib.suppress(Exception):
if not self._unsafe and output_type is not str:
output_value = ast.literal_eval(output_value)
This check only special-cases the exact str type. Any Union including str still evaluates output_type is not str as True.
To Reproduce
from haystack.components.routers import ConditionalRouter
routes = [
{
"condition": "{{True}}",
"output": "{{value}}",
"output_name": "result",
"output_type": str | None,
}
]
router = ConditionalRouter(routes, validate_output_type=True)
result = router.run(value="42")
# Expected: {"result": "42"}
# Actual: raises ValueError (int 42 doesn't match str | None)
Without validate_output_type=True, this silently returns 42 (int) instead of "42" (str) to the next pipeline component.
Context
PR #12322 fixed this same class of bug for the exact output_type=str case (see test_string_output_type_preserved_over_literal_eval), but didn't generalize to Unions that include str, which is a very normal way to declare an optional string output.
Proposed fix
Add a helper that checks whether str is output_type itself or a member of a Union output_type, and use that instead of the direct is not str check. I have a fix and passing regression test ready — happy to open a PR.
Environment
Haystack main branch, Python 3.12.4
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.