<#3810 bug: child streams with the same name all s...
# meltano-repo-activity
g
#3810 bug: child streams with the same name all sync, but a top-level duplicate is replaced Issue created by ReubenFrankel Singer SDK Version 0.54.7 (the code is the same on
main
) Is this a regression? • Yes Python Version 3.10 Bug scope Taps (catalog, state, etc.) Operating System Linux Description When
discover_streams()
returns two streams with the same name, a top-level stream is replaced by the last one, but a child stream is not: every child stream of that name syncs, and the stream gets one set of records from each.
Tap.streams
keeps the last stream of a name, so the catalog and the top-level sync loop see one stream.
Tap.load_streams()
adds every discovered stream to
parent.child_streams
before that happens, and
Stream._sync_children()
syncs each child in that list that is selected. The catalog entry for the name selects all of them. A tap hits this when it lets a user-defined stream replace a built-in stream of the same name, for example a custom query stream. from singer_sdk import Stream, Tap from singer_sdk import typing as th class Parent(Stream): name = "parent" schema = th.PropertiesList(th.Property("id", th.IntegerType)).to_dict() def get_records(self, context): yield {"id": 1} def get_child_context(self, record, context): return {"parent_id": record["id"]} class Child(Stream): name = "child" parent_stream_type = Parent schema = th.PropertiesList(th.Property("source", th.StringType)).to_dict() def get_records(self, context): yield {"source": type(self).name} class ChildOverride(Child): pass class MyTap(Tap): name = "tap-example" config_jsonschema = th.PropertiesList().to_dict() def discover_streams(self): return [Parent(self), Child(self), ChildOverride(self)] MyTap(config={}).sync_all() The
child
stream gets two records: {"stream": "child", "record": {"source": "Child"}} {"stream": "child", "record": {"source": "ChildOverride"}} Without
parent_stream_type = Parent
on
Child
, it gets one record, from
ChildOverride
. The two streams do not need to be different classes. Two instances of one class with the same name also both sync as children. Possible fixes, in `load_streams()`: • Keep only the last stream of each name before the parent-child links are built, which matches
Tap.streams
. • Raise an error when two discovered streams have the same name. Link to Slack/Linen No response --- 🤖 Generated with Claude Code meltano/sdk