Skip to content

bug: [Bug] Memory leak in Observable subscription due to dataclass __eq__ collision in component._detach_observable_subscription #6776

Description

@vip-liutao

Duplicate Check

Describe the bug

There is a serious memory leak / subscription leak when using ft.use_state with ObservableSubscription inside a @ft.component.In Component._detach_observable_subscription, the code checks if a subscription is attached using the in operator.
Currently, using component args explicitly when managing the hooks can avoid this problem, as it bypasses or overrides the mismatched context during state restoration. However, this is just a temporary bypass, and the underlying framework level bug still needs to be resolved.

Code sample

Code
def _detach_observable_subscription(self, subscription: ObservableSubscription):
    """
    Dispose and remove one observable subscription if still attached.

    Args:
        subscription: Subscription to detach.
    """

    if subscription in self._state.observable_subscriptions:
        subscription.dispose()
        self._state.observable_subscriptions.remove(subscription)

@ft.component
def TaskContent():
    state_a, _ = ft.use_state(ObservableA())
    state_b, _ = ft.use_state(ObservableB())

To reproduce

using ft.use_state multiple times

Expected behavior

No response

Screenshots / Videos

Captures

[Upload media here]

Operating System

Windows

Operating system details

Windows 10

Flet version

0.86.5

Regression

I'm not sure / I don't know

Suggestions

However, since ObservableSubscription is decorated with a default @DataClass, Python automatically generates an eq method that compares object fields rather than object identities (id). In this lifecycle helper, the fields often collide (e.g., sharing the same owner/component), causing subscription in self._state.observable_subscriptions to evaluate to True for completely different subscription instances (different id).

Logs

Logs
[Paste your logs here]

Additional details

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions