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
- In XML, only use <com.google.android.material.tabs.TabItem android:text="..."/> children.
- To show icons/badges/labels, use Tab APIs (setIcon, setCustomView, getOrCreateBadge) instead of adding views.
- 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
- Only declare <com.google.android.material.tabs.TabItem> children in TabLayout XML.
- Use tab.setCustomView()/setIcon()/getOrCreateBadge() instead of adding views directly.
- Lint for raw addView calls on TabLayout.
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
- Tab belongs to a different TabLayout.
- Tab does not belong to this TabLayout.
- Tab not attached to a TabLayout
- Stop indicator size must be >= 0.
- %1$s requires a value for the %2$s attribute to be set in yo
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/7f1ea9e6e610687b.
Report an issue: GitHub.