material-components/material-components-android · error · IllegalStateException
Attempted to set ShapeAppearanceModel on a MaterialButton wh
Error message
Attempted to set ShapeAppearanceModel on a MaterialButton which has an overwritten background.
What it means
setShapeAppearanceModel() on MaterialButton delegates to MaterialButtonHelper, which can only apply a shape to the button's own original MaterialShapeDrawable background. If the background has been overwritten (isUsingOriginalBackground() at MaterialButton.java:1958 is false because materialButtonHelper.isBackgroundOverwritten()), there is no shape drawable left to mutate, so the method throws IllegalStateException instead of silently doing nothing. A background counts as overwritten when setBackground()/setBackgroundResource() (or android:background in XML) replaced the material-styled drawable.
Source
Thrown at lib/java/com/google/android/material/button/MaterialButton.java:1850
*/
public void setCheckable(boolean checkable) {
if (isUsingOriginalBackground()) {
materialButtonHelper.setCheckable(checkable);
}
}
/**
* Sets the {@link ShapeAppearanceModel} used for this {@link MaterialButton}'s original
* drawables.
*
* @throws IllegalStateException if the MaterialButton's background has been overwritten.
*/
@Override
public void setShapeAppearanceModel(@NonNull ShapeAppearanceModel shapeAppearanceModel) {
if (isUsingOriginalBackground()) {
materialButtonHelper.setShapeAppearance(shapeAppearanceModel);
} else {
throw new IllegalStateException(
"Attempted to set ShapeAppearanceModel on a MaterialButton which has an overwritten"
+ " background.");
}
}
/**
* Returns the {@link ShapeAppearanceModel} used for this {@link MaterialButton}'s original
* drawables.
*
* <p>This {@link ShapeAppearanceModel} can be modified to change the component's shape.
*
* @throws IllegalStateException if the MaterialButton's background has been overwritten.
*/
@NonNull
@Override
public ShapeAppearanceModel getShapeAppearanceModel() {
if (isUsingOriginalBackground()) {
return materialButtonHelper.getShapeAppearanceModel();View on GitHub (pinned to ac7e18efee)
Solutions
- Remove android:background / setBackground calls so the button keeps its original MaterialShapeDrawable, then set the shape through setShapeAppearanceModel().
- If a custom background is required, define the shape in the background drawable itself (shape drawable / custom MaterialShapeDrawable) instead of calling setShapeAppearanceModel.
- Guard the call: if (button.isUsingOriginalBackground()) — or catch IllegalStateException — before applying shared shape logic to arbitrary buttons.
Example fix
<!-- before -->
<com.google.android.material.button.MaterialButton
android:background="@drawable/custom_bg"
... />
<!-- after -->
<com.google.android.material.button.MaterialButton
app:backgroundTint="@color/custom_tint"
app:strokeColor="@color/custom_stroke"
... /> Defensive patterns
Strategy: type-guard
Validate before calling
if (button.getBackground() instanceof MaterialShapeDrawable) {
button.setShapeAppearanceModel(model);
} Type guard
static boolean canReshape(Button b) {
return b instanceof MaterialButton && b.getBackground() instanceof MaterialShapeDrawable;
} Try / catch
try { button.setShapeAppearanceModel(model); } catch (IllegalStateException e) { Log.w(TAG, "background overwritten; skipping shape change"); } Prevention
- Ban android:background on MaterialButton in your design-system lint rules.
- Express custom looks via app:backgroundTint/strokeColor/shapeAppearance attributes instead.
- Centralize shape changes in one utility that guards with instanceof before calling.
When it happens
Trigger: Declaring the button with android:background="@drawable/my_bg" (or calling setBackground/setBackgroundResource on it) and later calling setShapeAppearanceModel(...). Also calling setShapeAppearanceModel after app:backgroundTint=null-style overrides that force the helper into the overwritten state.
Common situations: A design system wraps MaterialButton and applies a custom ripple/background drawable from XML, then app code (or a shared corner-rounding utility) tries to corners-round every button via getShapeAppearanceModel().newBuilder()...build(). Also migrating from Button to MaterialButton while keeping the old android:background attribute.
Related errors
- Attempted to get ShapeAppearanceModel from a MaterialButton
- Attempted to set ShapeAppearance on a MaterialButton which h
- Attempted to get ShapeAppearance from a MaterialButton which
- secondaryIconGravity cannot have the same alignment as iconG
- Scroll bar must contain a child to calculate interpolation.
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/08ffa2edde4fdcbf.
Report an issue: GitHub.