Skip to content

fix: serialize nested chat generators via component_to_dict in FallbackChatGenerator - #11847

Merged
sjrl merged 2 commits into
deepset-ai:mainfrom
rautaditya2606:fix-fallback-serialization
Jul 2, 2026
Merged

fix: serialize nested chat generators via component_to_dict in FallbackChatGenerator #11847
sjrl merged 2 commits into
deepset-ai:mainfrom
rautaditya2606:fix-fallback-serialization

Conversation

@rautaditya2606

@rautaditya2606 rautaditya2606 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #11846.

Proposed Changes

  • Updated FallbackChatGenerator.to_dict() in haystack/components/generators/chat/fallback.py to use component_to_dict() instead of directly calling .to_dict() on nested chat generators.
  • Added unit tests in test_fallback.py covering:
    • serialization/deserialization of mixed fallback chains (components with and without explicit to_dict() methods),
    • preservation of fallback ordering after a serialization round-trip,
    • successful round-trip execution after deserialization,
    • fail-loud behavior for non-serializable components.
  • Added release notes describing the serialization fix.

How did you test it?

hatch run test:unit test/components/generators/chat/test_fallback.py

Result:

26 passed, 2 warnings

Notes for the reviewer

Root cause

FallbackChatGenerator serialized its nested chat generators using:

chat_generators=[
    gen.to_dict()
    for gen in self.chat_generators
    if hasattr(gen, "to_dict")
]

This bypassed Haystack's standard serialization helper (component_to_dict()), which supports components that do not implement explicit to_dict()/from_dict() methods by falling back to constructor-based serialization. As a result, otherwise serializable components were silently omitted from the serialized representation.

Reproducer

from haystack import component
from haystack.components.generators.chat.fallback import FallbackChatGenerator
from haystack.dataclasses import ChatMessage


@component
class CustomGeneratorWithoutSerDe:
    def __init__(self, text: str = "custom_ok"):
        self.text = text

    def run(self, messages, **kwargs):
        return {"replies": [ChatMessage.from_assistant(self.text)]}


original = FallbackChatGenerator(
    chat_generators=[CustomGeneratorWithoutSerDe()]
)

data = original.to_dict()

# Before fix:
# data["init_parameters"]["chat_generators"] == []

# After fix:
# data["init_parameters"]["chat_generators"] contains the serialized component.

Precedent

This change follows the same serialization pattern already used by Agent.to_dict(), which serializes nested components through component_to_dict().

Checklist

Copilot AI review requested due to automatic review settings July 1, 2026 17:46
@rautaditya2606
rautaditya2606 requested a review from a team as a code owner July 1, 2026 17:46
@rautaditya2606
rautaditya2606 requested review from sjrl and removed request for a team July 1, 2026 17:46
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

@rautaditya2606 is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes FallbackChatGenerator nested-component serialization so custom chat generators that rely on Haystack’s default constructor-based SerDe are no longer silently dropped during to_dict() / from_dict() round-trips.

Changes:

  • Updated FallbackChatGenerator.to_dict() to serialize nested generators via component_to_dict() (instead of filtering on hasattr(..., "to_dict")).
  • Added unit tests covering mixed fallback chains, order preservation, round-trip execution, and fail-loud behavior for non-serializable components.
  • Added a release note documenting the serialization fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
haystack/components/generators/chat/fallback.py Uses component_to_dict() for nested generator serialization, preventing silent omission of otherwise-serializable components.
test/components/generators/chat/test_fallback.py Adds regression tests for serialization/deserialization correctness and explicit failure on non-serializable init parameters.
releasenotes/notes/fix_fallback_chat_generator_serialization-9498ee2bbe2971be.yaml Documents the behavioral fix in release notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack/components/generators/chat
  fallback.py
Project Total  

This report was generated by python-coverage-comment-action



def test_serialization_with_custom_generators_without_to_dict():
from haystack.core.errors import SerializationError

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move the import to the top of the file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, i've moved the import to the top of the file
thanks

@sjrl sjrl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thanks for the contribution!

@sjrl
sjrl merged commit fe6c923 into deepset-ai:main Jul 2, 2026
26 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug]: FallbackChatGenerator silently omits serializable chat generators without explicit to_dict()

3 participants