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

Only TabItem instances can be added to TabLayout

Error message

Only TabItem instances can be added to TabLayout

What it means

TabLayout overrides ViewGroup.addView so that any child added to it is interpreted as tab metadata: only TabItem elements are accepted (they are converted into tabs via addTabFromItemView). Any other View passed to addView hits addViewInternal's else branch and throws IllegalArgumentException.

Source

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

  public void addView(View child, int index) {
    addViewInternal(child);
  }

  @Override
  public void addView(View child, ViewGroup.LayoutParams params) {
    addViewInternal(child);
  }

  @Override
  public void addView(View child, int index, ViewGroup.LayoutParams params) {
    addViewInternal(child);
  }

  private void addViewInternal(final View child) {
    if (child instanceof TabItem) {
      addTabFromItemView((TabItem) child);
    } else {
      throw new IllegalArgumentException("Only TabItem instances can be added to TabLayout");
    }
  }

  @NonNull
  private LinearLayout.LayoutParams createLayoutParamsForTabs() {
    final LinearLayout.LayoutParams lp =
        new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
    updateTabViewLayoutParams(lp);
    return lp;
  }

  private void updateTabViewLayoutParams(@NonNull LinearLayout.LayoutParams lp) {
    if (mode == MODE_FIXED && tabGravity == GRAVITY_FILL) {
      lp.width = 0;
      lp.weight = 1;
    } else {
      lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
      lp.weight = 0;

View on GitHub (pinned to ac7e18efee)

Solutions

  1. In XML, only use <com.google.android.material.tabs.TabItem android:text="..."/> children.
  2. To show icons/badges/labels, use Tab APIs (setIcon, setCustomView, getOrCreateBadge) instead of adding views.
  3. For custom content per tab, supply tab.setCustomView(layoutRes) rather than addView.

Example fix

<!-- before -->
<com.google.android.material.tabs.TabLayout>
  <TextView android:text="Tab 1"/>
</com.google.android.material.tabs.TabLayout>

<!-- after -->
<com.google.android.material.tabs.TabLayout>
  <com.google.android.material.tabs.TabItem android:text="Tab 1"/>
</com.google.android.material.tabs.TabLayout>
Defensive patterns

Strategy: type-guard

Type guard

if (child instanceof com.google.android.material.tabs.TabItem) {
  tabLayout.addView(child);
} else {
  throw new IllegalArgumentException("Child must be TabItem, was " + child.getClass().getName());
}

Prevention

When it happens

Trigger: In XML, placing any element other than <com.google.android.material.tabs.TabItem> inside the TabLayout (e.g. TextView, ImageView, Space). Programmatically, calling tabLayout.addView(someView).

Common situations: Declarative XML with a typo'd or wrong child element; trying to overlay a badge/icon view directly inside TabLayout instead of using tab.setBadge()/tab.setIcon(); using TabItem without the fully qualified name.

Related errors


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