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

  1. Remove android:background / setBackground calls so the button keeps its original MaterialShapeDrawable, then set the shape through setShapeAppearanceModel().
  2. If a custom background is required, define the shape in the background drawable itself (shape drawable / custom MaterialShapeDrawable) instead of calling setShapeAppearanceModel.
  3. 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

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


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