Bug description

The embedded dashboard continues to make fetchGuestToken calls even after the component containing it has been destroyed and unmount() has been called. This leads to unnecessary network requests and potential memory leaks in Single Page Applications (SPAs).

@superset-ui/embedded-sdk version: 0.1.3 Framework: Angular 16 Browser: 136.0.7103.114

Steps to Reproduce

  1. Create an Angular component that embeds a Superset dashboard using embedDashboard()
  2. Configure the dashboard with fetchGuestToken callback
  3. Navigate to the component and let the dashboard load successfully
  4. Navigate away from the component (triggering ngOnDestroy)
  5. Call unmount() on the dashboard instance in the cleanup method
  6. Wait approximately 5 minutes
  7. Observe network requests in browser DevTools

Expected Behavior

After calling unmount() on the dashboard instance, no further fetchGuestToken calls should be made, and all internal timers/intervals should be cleared.

Actual Behavior

The fetchGuestToken callback continues to be invoked approximately 5 minutes after navigation, even though:

  • The component has been destroyed
  • unmount() was called on the dashboard instance
  • The DOM container has been cleared

Code Example

export class AnalyticsComponent implements OnInit, OnDestroy {
  private currentDashboard: EmbeddedDashboard | null = null;

  async ngOnInit() {
    this.currentDashboard = await embedDashboard({
      id: 'dashboard-id',
      supersetDomain: 'https://superset.example.com',
      mountPoint: this.containerElement,
      fetchGuestToken: () => this.fetchGuestToken(), // This continues to be called!
      dashboardUiConfig: {
        hideTitle: true,
        filters: { expanded: false }
      }
    });
  }

  ngOnDestroy() {
    this.cleanup();
  }

  private cleanup() {
    if (this.currentDashboard) {
      try {
        this.currentDashboard.unmount(); // Called but doesn't stop token fetching
        this.currentDashboard = null;
      } catch (error) {
        console.error('Error unmounting dashboard:', error);
      }
    }

    // Clear container
    if (this.containerElement) {
      this.containerElement.innerHTML = '';
    }
  }

  private async fetchGuestToken(): Promise<string> {
    console.log('Token fetch called - this should not happen after unmount!');
    // ... token fetching logic
  }
}

Potential Root Cause

The embedded dashboard appears to maintain internal timers/intervals for token refresh that are not properly cleared by the unmount() method. This suggests:

  • Internal setTimeout/setInterval calls are not being tracked and cleared
  • The unmount() method may not be cleaning up all dashboard lifecycle processes
  • Async operations initiated before unmount may still complete after unmount

Screenshots/recordings

No response

Superset version

master / latest-dev

Python version

3.9

Node version

16

Browser

Chrome

Additional context

No response

Checklist

  • [x] I have searched Superset docs and Slack and didn't find a solution to my problem.
  • [x] I have searched the GitHub issue tracker and didn't find a similar bug report.
  • [ ] I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Comment From: dosubot[bot]

Hi @NewtonFernandis! I'm Dosu and I’m helping the superset team.

This is a real bug in the current @superset-ui/embedded-sdk: the SDK schedules fetchGuestToken refreshes using setTimeout, but the unmount() method only clears the DOM and does not cancel or track these timers. As a result, fetchGuestToken continues to be called after unmount(), even after the Angular component is destroyed. There is no built-in mechanism to stop these background refreshes or cancel in-flight async operations after unmount()—which can lead to memory leaks and unwanted network requests in SPAs like Angular apps. You can see this in the SDK code, where setTimeout is used recursively for token refresh, but unmount() does not clear these timers or provide any cleanup logic for them (source).

There are no official workarounds or best practices documented for this scenario. As a temporary mitigation, you could try monkey-patching the SDK to track and clear the timer yourself, or wrap fetchGuestToken in a guard that disables it after unmount, but these are not officially supported solutions. This is a lifecycle management gap in the SDK and would need to be addressed in the library itself for a robust fix.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

Comment From: NewtonFernandis

Okay 👍, Thank you.