material-components/material-components-android · error · IllegalArgumentException

Tab does not belong to this TabLayout.

Error message

Tab does not belong to this TabLayout.

What it means

removeTab(tab) verifies tab.parent == this; Tab objects carry an internal owner reference set when created via newTab(). Removing a tab owned by another TabLayout (or one never added) throws IllegalArgumentException, since the owning layout's tab list is the only valid source of positions.

Source

Thrown at lib/java/com/google/android/material/tabs/TabLayout.java:1063

  /**
   * Returns the position of the current selected tab.
   *
   * @return selected tab position, or {@code -1} if there isn't a selected tab.
   */
  public int getSelectedTabPosition() {
    return selectedTab != null ? selectedTab.getPosition() : -1;
  }

  /**
   * Remove a tab from the layout. If the removed tab was selected it will be deselected and another
   * tab will be selected if present.
   *
   * @param tab The tab to remove
   */
  public void removeTab(@NonNull Tab tab) {
    if (tab.parent != this) {
      throw new IllegalArgumentException("Tab does not belong to this TabLayout.");
    }

    removeTabAt(tab.getPosition());
  }

  /**
   * Remove a tab from the layout. If the removed tab was selected it will be deselected and another
   * tab will be selected if present.
   *
   * @param position Position of the tab to remove
   */
  public void removeTabAt(int position) {
    final int selectedTabPosition = selectedTab != null ? selectedTab.getPosition() : 0;
    removeTabViewAt(position);

    final Tab removedTab = tabs.remove(position);
    if (removedTab != null) {
      removedTab.reset();

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Remove by position instead: tabLayout.removeTabAt(position) using a position you track.
  2. Prefer getTabAt(position) to fetch the tab right before removal so it is guaranteed to belong to this layout.
  3. To clear all tabs, call tabLayout.removeAllTabs() rather than iterating cached Tab objects.

Example fix

// before
tabLayout.removeTab(cachedTab); // cachedTab from another/stale TabLayout

// after
Tab current = tabLayout.getTabAt(position);
if (current != null) tabLayout.removeTab(current);
Defensive patterns

Strategy: validation

Validate before calling

// Prefer positional removal, which cannot cross-own:
public static void removeTabAtSafe(@NonNull TabLayout layout, int position) {
  if (position >= 0 && position < layout.getTabCount()) layout.removeTabAt(position);
}

Prevention

When it happens

Trigger: Calling tabLayout.removeTab(tab) where tab came from a different TabLayout's newTab(), or removing the same tab twice after it was already removed and its parent reference cleared.

Common situations: Multiple TabLayouts sharing tab-building code; caching Tab references across adapter refreshes and removing stale tabs; races between tab removal and UI recreation.

Related errors


AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14). Data as JSON: /api/errors/4c9227b5ede3e3b0. Report an issue: GitHub.