#12625·haystack

OutputAdapter silently coerces string output to another type when output_type is a Union including str.

Author: Anishithavaram-4242Created Sep 5, 2026Updated Sep 14, 2026
LabelsP2

Describe the bug OutputAdapter.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]). A rendered value like "42" declared with output_type=str | None is silently coerced to the int 42 instead of being preserved as the string "42".

Affected code haystack/components/converters/output_adapter.py, inside run():

python
with contextlib.suppress(Exception):
    if not self._unsafe and self.output_type is not str:
        output_result = ast.literal_eval(output_result)

To Reproduce

python
from haystack.components.converters import OutputAdapter

adapter = OutputAdapter(template="{{ reply }}", output_type=str | None)
result = adapter.run(reply="42")
# Expected: {"output": "42"}
# Actual: {"output": 42}  (coerced to int)

Context This is the same class of bug just found and fixed in ConditionalRouter (see #12617, PR #12620), which has the identical output_type is not str pattern. I confirmed via GitHub search that no existing open issue or PR currently covers this specific OutputAdapter case before filing.

Proposed fix Add a helper checking whether str is output_type itself or a member of a Union output_type, matching the same fix pattern used for ConditionalRouter. I have a fix and passing regression test ready.

Environment Haystack main branch, Python 3.12.4