material-components/material-components-android · error · IllegalArgumentException
MaterialSplitButton can only hold MaterialButtons.
Error message
MaterialSplitButton can only hold MaterialButtons.
What it means
MaterialSplitButton is a two-button container (leading action + trailing 'add' chevron) whose implementation depends on every child being a MaterialButton: it casts children to MaterialButton in addView to set checkability, accessibility class name, shape and margins (MaterialSplitButton.java:107). addView therefore throws IllegalArgumentException immediately when any non-MaterialButton view is added, including generic Button subclasses that are not MaterialButtons.
Source
Thrown at lib/java/com/google/android/material/button/MaterialSplitButton.java:99
public MaterialSplitButton(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, R.attr.materialSplitButtonStyle);
}
public MaterialSplitButton(
@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
}
/**
* This override prohibits Views other than {@link MaterialButton} to be added where the leading
* {@link MaterialButton} has either an icon and/or a label and the trailing {@link
* MaterialButton} has an animated vector drawable as an icon. It also makes updates to the add
* button shape and margins.
*/
@Override
public void addView(@NonNull View child, int index, @Nullable ViewGroup.LayoutParams params) {
if (!(child instanceof MaterialButton)) {
throw new IllegalArgumentException("MaterialSplitButton can only hold MaterialButtons.");
}
if (getChildCount() > REQUIRED_BUTTON_COUNT) {
throw new IllegalArgumentException("MaterialSplitButton can only hold two MaterialButtons.");
}
MaterialButton buttonChild = (MaterialButton) child;
super.addView(child, index, params);
if (indexOfChild(child) == 1) {
buttonChild.setCheckable(true);
buttonChild.setA11yClassName(Button.class.getName());
// Set initial content description based on checked state when focused.
ViewCompat.setStateDescription(
buttonChild,
getResources()
.getString(
buttonChild.isChecked()
? R.string.mtrl_button_expanded_content_description
: R.string.mtrl_button_collapsed_content_description));View on GitHub (pinned to ac7e18efee)
Solutions
- Use fully-qualified <com.google.android.material.button.MaterialButton> elements as the only children of MaterialSplitButton.
- If you added views in code, replace addView(new X(...)) with addView(new MaterialButton(context, null, attr)) or inflate a MaterialButton.
- Do not put intermediate containers (LinearLayout, Space) inside the split button — it accepts exactly two MaterialButtons, nothing else.
Example fix
<!-- before -->
<com.google.android.material.button.MaterialSplitButton ...>
<Button android:text="Save" ... />
</com.google.android.material.button.MaterialSplitButton>
<!-- after -->
<com.google.android.material.button.MaterialSplitButton ...>
<com.google.android.material.button.MaterialButton
android:text="Save" ... />
<com.google.android.material.button.MaterialButton
app:icon="@drawable/ic_chevron" ... />
</com.google.android.material.button.MaterialSplitButton> Defensive patterns
Strategy: type-guard
Validate before calling
if (child instanceof MaterialButton) {
splitButton.addView(child);
} Type guard
static boolean isValidSplitChild(View v) {
return v instanceof MaterialButton;
} Try / catch
try { splitButton.addView(view); } catch (IllegalArgumentException e) { throw new IllegalStateException("MaterialSplitButton children must be MaterialButton", e); } Prevention
- Always use the fully-qualified <com.google.android.material.button.MaterialButton> tag inside the split button.
- Never insert plain Button/ImageView/containers as direct children.
- Add a custom lint rule banning non-material button tags inside MaterialSplitButton.
When it happens
Trigger: Inflating or programmatically adding a plain Button, ImageButton, TextView or any custom View into a MaterialSplitButton — e.g. <Button> children in XML, or splitButton.addView(new ImageView(context)). Even AppCompatButton is rejected because the instanceof check is against MaterialButton.
Common situations: Writing the split button in XML and using the platform <Button> tag out of habit (the same mistake people make inside MaterialButtonToggleGroup). XML inflation calls addView for each child, so the crash occurs at setContentView/inflate time with a stack trace rooted in LayoutInflater.
Related errors
- MaterialSplitButton can only hold two MaterialButtons.
- secondaryIconGravity cannot have the same alignment as iconG
- The wrap overflow mode is not compatible to the vertical ori
- The wrap overflow mode is not compatible with wrap_content l
- We already have an EditText, can only have one
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/8dddaa213f893268.
Report an issue: GitHub.